|
Packit Service |
d40955 |
/*
|
|
Packit Service |
d40955 |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
d40955 |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
d40955 |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
d40955 |
* of the License, or (at your option) any later version.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
d40955 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
d40955 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
d40955 |
* GNU General Public License for more details.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
d40955 |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
d40955 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
d40955 |
* 02110-1301, USA.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/refCountsInternals.h#4 $
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#ifndef REF_COUNTS_INTERNALS_H
|
|
Packit Service |
d40955 |
#define REF_COUNTS_INTERNALS_H
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include "refCounts.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include "journalPoint.h"
|
|
Packit Service |
d40955 |
#include "referenceBlock.h"
|
|
Packit Service |
d40955 |
#include "slab.h"
|
|
Packit Service |
d40955 |
#include "blockAllocatorInternals.h"
|
|
Packit Service |
d40955 |
#include "waitQueue.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Represents the possible status of a block.
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
typedef enum referenceStatus {
|
|
Packit Service |
d40955 |
RS_FREE, // this block is free
|
|
Packit Service |
d40955 |
RS_SINGLE, // this block is singly-referenced
|
|
Packit Service |
d40955 |
RS_SHARED, // this block is shared
|
|
Packit Service |
d40955 |
RS_PROVISIONAL // this block is provisionally allocated
|
|
Packit Service |
d40955 |
} ReferenceStatus;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* The SearchCursor represents the saved position of a free block search.
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
typedef struct searchCursor {
|
|
Packit Service |
d40955 |
/** The reference block containing the current search index */
|
|
Packit Service |
d40955 |
ReferenceBlock *block;
|
|
Packit Service |
d40955 |
/** The position at which to start searching for the next free counter */
|
|
Packit Service |
d40955 |
SlabBlockNumber index;
|
|
Packit Service |
d40955 |
/** The position just past the last valid counter in the current block */
|
|
Packit Service |
d40955 |
SlabBlockNumber endIndex;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** A pointer to the first reference block in the slab */
|
|
Packit Service |
d40955 |
ReferenceBlock *firstBlock;
|
|
Packit Service |
d40955 |
/** A pointer to the last reference block in the slab */
|
|
Packit Service |
d40955 |
ReferenceBlock *lastBlock;
|
|
Packit Service |
d40955 |
} SearchCursor;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/*
|
|
Packit Service |
d40955 |
* RefCounts structure
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* A reference count is maintained for each PhysicalBlockNumber. The vast
|
|
Packit Service |
d40955 |
* majority of blocks have a very small reference count (usually 0 or 1).
|
|
Packit Service |
d40955 |
* For references less than or equal to MAXIMUM_REFS (254) the reference count
|
|
Packit Service |
d40955 |
* is stored in counters[pbn].
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
struct refCounts {
|
|
Packit Service |
d40955 |
/** The slab of this reference block */
|
|
Packit Service |
d40955 |
Slab *slab;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** The size of the counters array */
|
|
Packit Service |
d40955 |
uint32_t blockCount;
|
|
Packit Service |
d40955 |
/** The number of free blocks */
|
|
Packit Service |
d40955 |
uint32_t freeBlocks;
|
|
Packit Service |
d40955 |
/** The array of reference counts */
|
|
Packit Service |
d40955 |
ReferenceCount *counters; // use ALLOCATE to align data ptr
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** The saved block pointer and array indexes for the free block search */
|
|
Packit Service |
d40955 |
SearchCursor searchCursor;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** A list of the dirty blocks waiting to be written out */
|
|
Packit Service |
d40955 |
WaitQueue dirtyBlocks;
|
|
Packit Service |
d40955 |
/** The number of blocks which are currently writing */
|
|
Packit Service |
d40955 |
size_t activeCount;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** A waiter object for updating the slab summary */
|
|
Packit Service |
d40955 |
Waiter slabSummaryWaiter;
|
|
Packit Service |
d40955 |
/** Whether slab summary update is in progress */
|
|
Packit Service |
d40955 |
bool updatingSlabSummary;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** The notifier for read-only mode */
|
|
Packit Service |
d40955 |
ReadOnlyNotifier *readOnlyNotifier;
|
|
Packit Service |
d40955 |
/** The refcount statistics, shared by all refcounts in our physical zone */
|
|
Packit Service |
d40955 |
AtomicRefCountStatistics *statistics;
|
|
Packit Service |
d40955 |
/** The layer PBN for the first ReferenceBlock */
|
|
Packit Service |
d40955 |
PhysicalBlockNumber origin;
|
|
Packit Service |
d40955 |
/** The latest slab journal entry this RefCounts has been updated with */
|
|
Packit Service |
d40955 |
JournalPoint slabJournalPoint;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** The number of reference count blocks */
|
|
Packit Service |
d40955 |
uint32_t referenceBlockCount;
|
|
Packit Service |
d40955 |
/** reference count block array */
|
|
Packit Service |
d40955 |
ReferenceBlock blocks[];
|
|
Packit Service |
d40955 |
};
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Convert a reference count to a reference status.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param count The count to convert
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return The appropriate reference status
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
__attribute__((warn_unused_result))
|
|
Packit Service |
d40955 |
ReferenceStatus referenceCountToStatus(ReferenceCount count);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Convert a generic VDOCompletion to a RefCounts.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param completion The completion to convert
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return The completion as a RefCounts
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
RefCounts *asRefCounts(VDOCompletion *completion)
|
|
Packit Service |
d40955 |
__attribute__((warn_unused_result));
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Get the reference block that covers the given block index (exposed for
|
|
Packit Service |
d40955 |
* testing).
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param refCounts The refcounts object
|
|
Packit Service |
d40955 |
* @param index The block index
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
ReferenceBlock *getReferenceBlock(RefCounts *refCounts, SlabBlockNumber index)
|
|
Packit Service |
d40955 |
__attribute__((warn_unused_result));
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Find the reference counters for a given block (exposed for testing).
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param block The ReferenceBlock in question
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return A pointer to the reference counters for this block
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
ReferenceCount *getReferenceCountersForBlock(ReferenceBlock *block)
|
|
Packit Service |
d40955 |
__attribute__((warn_unused_result));
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Copy data from a reference block to a buffer ready to be written out
|
|
Packit Service |
d40955 |
* (exposed for testing).
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param block The block to copy
|
|
Packit Service |
d40955 |
* @param buffer The char buffer to fill with the packed block
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void packReferenceBlock(ReferenceBlock *block, void *buffer);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Get the reference status of a block. Exposed only for unit testing.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param [in] refCounts The refcounts object
|
|
Packit Service |
d40955 |
* @param [in] pbn The physical block number
|
|
Packit Service |
d40955 |
* @param [out] statusPtr Where to put the status of the block
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return A success or error code, specifically:
|
|
Packit Service |
d40955 |
* VDO_OUT_OF_RANGE if the pbn is out of range.
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
int getReferenceStatus(RefCounts *refCounts,
|
|
Packit Service |
d40955 |
PhysicalBlockNumber pbn,
|
|
Packit Service |
d40955 |
ReferenceStatus *statusPtr)
|
|
Packit Service |
d40955 |
__attribute__((warn_unused_result));
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Find the first block with a reference count of zero in the specified range
|
|
Packit Service |
d40955 |
* of reference counter indexes. Exposed for unit testing.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param [in] refCounts The reference counters to scan
|
|
Packit Service |
d40955 |
* @param [in] startIndex The array index at which to start scanning
|
|
Packit Service |
d40955 |
* (included in the scan)
|
|
Packit Service |
d40955 |
* @param [in] endIndex The array index at which to stop scanning
|
|
Packit Service |
d40955 |
* (excluded from the scan)
|
|
Packit Service |
d40955 |
* @param [out] indexPtr A pointer to hold the array index of the free block
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return true if a free block was found in the specified range
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
bool findFreeBlock(const RefCounts *refCounts,
|
|
Packit Service |
d40955 |
SlabBlockNumber startIndex,
|
|
Packit Service |
d40955 |
SlabBlockNumber endIndex,
|
|
Packit Service |
d40955 |
SlabBlockNumber *indexPtr)
|
|
Packit Service |
d40955 |
__attribute__((warn_unused_result));
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Request a RefCounts save its oldest dirty block asynchronously.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param refCounts The RefCounts object to notify
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void saveOldestReferenceBlock(RefCounts *refCounts);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Reset all reference counts back to RS_FREE.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param refCounts The reference counters to reset
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
void resetReferenceCounts(RefCounts *refCounts);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#endif // REF_COUNTS_INTERNALS_H
|