Blame source/vdo/base/refCountsInternals.h

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