Blame source/vdo/base/slab.h

Packit Service 7e342f
/*
Packit Service 7e342f
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service 7e342f
 *
Packit Service 7e342f
 * This program is free software; you can redistribute it and/or
Packit Service 7e342f
 * modify it under the terms of the GNU General Public License
Packit Service 7e342f
 * as published by the Free Software Foundation; either version 2
Packit Service 7e342f
 * of the License, or (at your option) any later version.
Packit Service 7e342f
 * 
Packit Service 7e342f
 * This program is distributed in the hope that it will be useful,
Packit Service 7e342f
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 7e342f
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 7e342f
 * GNU General Public License for more details.
Packit Service 7e342f
 * 
Packit Service 7e342f
 * You should have received a copy of the GNU General Public License
Packit Service 7e342f
 * along with this program; if not, write to the Free Software
Packit Service 7e342f
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 7e342f
 * 02110-1301, USA. 
Packit Service 7e342f
 *
Packit Service 7e342f
 * $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/slab.h#8 $
Packit Service 7e342f
 */
Packit Service 7e342f
Packit Service 7e342f
#ifndef VDO_SLAB_H
Packit Service 7e342f
#define VDO_SLAB_H
Packit Service 7e342f
Packit Service 7e342f
#include "permassert.h"
Packit Service 7e342f
Packit Service 7e342f
#include "adminState.h"
Packit Service 7e342f
#include "fixedLayout.h"
Packit Service 7e342f
#include "journalPoint.h"
Packit Service 7e342f
#include "referenceOperation.h"
Packit Service 7e342f
#include "ringNode.h"
Packit Service 7e342f
#include "types.h"
Packit Service 7e342f
Packit Service 7e342f
typedef uint32_t SlabBlockNumber;
Packit Service 7e342f
Packit Service 7e342f
typedef enum {
Packit Service 7e342f
  SLAB_REBUILT = 0,
Packit Service 7e342f
  SLAB_REPLAYING,
Packit Service 7e342f
  SLAB_REQUIRES_SCRUBBING,
Packit Service 7e342f
  SLAB_REQUIRES_HIGH_PRIORITY_SCRUBBING,
Packit Service 7e342f
  SLAB_REBUILDING,
Packit Service 7e342f
} SlabRebuildStatus;
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * This is the type declaration for the Slab type. (The struct tag is named
Packit Service 7e342f
 * vdoSlab to avoid a conflict with the linux kernel type). A Slab currently
Packit Service 7e342f
 * consists of a run of 2^23 data blocks, but that will soon change to
Packit Service 7e342f
 * dedicate a small number of those blocks for metadata storage for the
Packit Service 7e342f
 * reference counts and slab journal for the slab.
Packit Service 7e342f
 **/
Packit Service 7e342f
struct vdoSlab {
Packit Service 7e342f
  /** A RingNode to queue this slab in a BlockAllocator ring */
Packit Service 7e342f
  RingNode             ringNode;
Packit Service 7e342f
Packit Service 7e342f
  /** The BlockAllocator that owns this slab */
Packit Service 7e342f
  BlockAllocator      *allocator;
Packit Service 7e342f
Packit Service 7e342f
  /** The reference counts for the data blocks in this slab */
Packit Service 7e342f
  RefCounts           *referenceCounts;
Packit Service 7e342f
  /** The journal for this slab */
Packit Service 7e342f
  SlabJournal         *journal;
Packit Service 7e342f
Packit Service 7e342f
  /** The slab number of this slab */
Packit Service 7e342f
  SlabCount            slabNumber;
Packit Service 7e342f
  /** The offset in the allocator partition of the first block in this slab */
Packit Service 7e342f
  PhysicalBlockNumber  start;
Packit Service 7e342f
  /** The offset of the first block past the end of this slab */
Packit Service 7e342f
  PhysicalBlockNumber  end;
Packit Service 7e342f
  /** The starting translated PBN of the slab journal */
Packit Service 7e342f
  PhysicalBlockNumber  journalOrigin;
Packit Service 7e342f
  /** The starting translated PBN of the reference counts */
Packit Service 7e342f
  PhysicalBlockNumber  refCountsOrigin;
Packit Service 7e342f
Packit Service 7e342f
  /** The administrative state of the slab */
Packit Service 7e342f
  AdminState           state;
Packit Service 7e342f
  /** The status of the slab */
Packit Service 7e342f
  SlabRebuildStatus    status;
Packit Service 7e342f
  /** Whether the slab was ever queued for scrubbing */
Packit Service 7e342f
  bool                 wasQueuedForScrubbing;
Packit Service 7e342f
Packit Service 7e342f
  /** The priority at which this slab has been queued for allocation */
Packit Service 7e342f
  uint8_t              priority;
Packit Service 7e342f
};
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Measure and initialize the configuration to use for each slab.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param [in]  slabSize           The number of blocks per slab
Packit Service 7e342f
 * @param [in]  slabJournalBlocks  The number of blocks for the slab journal
Packit Service 7e342f
 * @param [out] slabConfig         The slab configuration to initialize
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return VDO_SUCCESS or an error code
Packit Service 7e342f
 **/
Packit Service 7e342f
int configureSlab(BlockCount  slabSize,
Packit Service 7e342f
                  BlockCount  slabJournalBlocks,
Packit Service 7e342f
                  SlabConfig *slabConfig)
Packit Service 7e342f
  __attribute__((warn_unused_result));
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Convert a Slab's RingNode back to the Slab.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param ringNode  The RingNode to convert
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return  The RingNode as a Slab
Packit Service 7e342f
 **/
Packit Service 7e342f
static inline Slab *slabFromRingNode(RingNode *ringNode)
Packit Service 7e342f
{
Packit Service 7e342f
  STATIC_ASSERT(offsetof(Slab, ringNode) == 0);
Packit Service 7e342f
  return (Slab *) ringNode;
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Get the physical block number of the start of the slab journal
Packit Service 7e342f
 * relative to the start block allocator partition.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slabConfig  The slab configuration of the VDO
Packit Service 7e342f
 * @param origin      The first block of the slab
Packit Service 7e342f
 **/
Packit Service 7e342f
__attribute__((warn_unused_result))
Packit Service 7e342f
PhysicalBlockNumber getSlabJournalStartBlock(const SlabConfig    *slabConfig,
Packit Service 7e342f
                                             PhysicalBlockNumber  origin);
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Construct a new, empty slab.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param [in]  slabOrigin       The physical block number within the block
Packit Service 7e342f
 *                               allocator partition of the first block in the
Packit Service 7e342f
 *                               slab
Packit Service 7e342f
 * @param [in]  allocator        The block allocator to which the slab belongs
Packit Service 7e342f
 * @param [in]  translation      The translation from the depot's partition to
Packit Service 7e342f
 *                               the physical storage
Packit Service 7e342f
 * @param [in]  recoveryJournal  The recovery journal of the VDO
Packit Service 7e342f
 * @param [in]  slabNumber       The slab number of the slab
Packit Service 7e342f
 * @param [in]  isNew            true if this slab is being
Packit Service 7e342f
 *                               allocated as part of a resize
Packit Service 7e342f
 * @param [out] slabPtr          A pointer to receive the new slab
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return VDO_SUCCESS or an error code
Packit Service 7e342f
 **/
Packit Service 7e342f
int makeSlab(PhysicalBlockNumber   slabOrigin,
Packit Service 7e342f
             BlockAllocator       *allocator,
Packit Service 7e342f
             PhysicalBlockNumber   translation,
Packit Service 7e342f
             RecoveryJournal      *recoveryJournal,
Packit Service 7e342f
             SlabCount             slabNumber,
Packit Service 7e342f
             bool                  isNew,
Packit Service 7e342f
             Slab                **slabPtr)
Packit Service 7e342f
  __attribute__((warn_unused_result));
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Allocate the reference counts for a slab.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab whose reference counts need allocation.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return VDO_SUCCESS or an error code
Packit Service 7e342f
 **/
Packit Service 7e342f
int allocateRefCountsForSlab(Slab *slab)
Packit Service 7e342f
  __attribute__((warn_unused_result));
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Destroy a slab and null out the reference to it.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slabPtr  The reference to the slab to destroy
Packit Service 7e342f
 **/
Packit Service 7e342f
void freeSlab(Slab **slabPtr);
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Get the physical zone number of a slab.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return The number of the slab's physical zone
Packit Service 7e342f
 **/
Packit Service 7e342f
ZoneCount getSlabZoneNumber(Slab *slab)
Packit Service 7e342f
  __attribute__((warn_unused_result));
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Check whether a slab is unrecovered.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab to check
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return true if the slab is unrecovered
Packit Service 7e342f
 **/
Packit Service 7e342f
static inline bool isUnrecoveredSlab(const Slab *slab)
Packit Service 7e342f
{
Packit Service 7e342f
  return (slab->status != SLAB_REBUILT);
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Check whether a slab is being replayed into.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab to check
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return true if the slab is replaying
Packit Service 7e342f
 **/
Packit Service 7e342f
static inline bool isReplayingSlab(const Slab *slab)
Packit Service 7e342f
{
Packit Service 7e342f
  return (slab->status == SLAB_REPLAYING);
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Check whether a slab is being rebuilt.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab to check
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return true if the slab is being rebuilt
Packit Service 7e342f
 **/
Packit Service 7e342f
static inline bool slabIsRebuilding(const Slab *slab)
Packit Service 7e342f
{
Packit Service 7e342f
  return (slab->status == SLAB_REBUILDING);
Packit Service 7e342f
}
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Mark a slab as replaying, during offline recovery.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab to mark
Packit Service 7e342f
 **/
Packit Service 7e342f
void markSlabReplaying(Slab *slab);
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Mark a slab as unrecovered, for online recovery.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab to mark
Packit Service 7e342f
 **/
Packit Service 7e342f
void markSlabUnrecovered(Slab *slab);
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Get the current number of free blocks in a slab.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab to query
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return the number of free blocks in the slab
Packit Service 7e342f
 **/
Packit Service 7e342f
BlockCount getSlabFreeBlockCount(const Slab *slab)
Packit Service 7e342f
  __attribute__((warn_unused_result));
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Increment or decrement the reference count of a block in a slab.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab          The slab containing the block (may be NULL when
Packit Service 7e342f
 *                      referencing the zero block)
Packit Service 7e342f
 * @param journalPoint  The slab journal entry corresponding to this change
Packit Service 7e342f
 * @param operation     The operation to perform on the reference count
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return VDO_SUCCESS or an error
Packit Service 7e342f
 **/
Packit Service 7e342f
int modifySlabReferenceCount(Slab               *slab,
Packit Service 7e342f
                             const JournalPoint *journalPoint,
Packit Service 7e342f
                             ReferenceOperation  operation)
Packit Service 7e342f
  __attribute__((warn_unused_result));
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Acquire a provisional reference on behalf of a PBN lock if the block it
Packit Service 7e342f
 * locks is unreferenced.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab which contains the block
Packit Service 7e342f
 * @param pbn   The physical block to reference
Packit Service 7e342f
 * @param lock  The lock
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return VDO_SUCCESS or an error
Packit Service 7e342f
 **/
Packit Service 7e342f
int acquireProvisionalReference(Slab                *slab,
Packit Service 7e342f
                                PhysicalBlockNumber  pbn,
Packit Service 7e342f
                                PBNLock             *lock)
Packit Service 7e342f
  __attribute__((warn_unused_result));
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Determine the index within the slab of a particular physical block number.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param [in]  slab                    The slab
Packit Service 7e342f
 * @param [in]  physicalBlockNumber     The physical block number
Packit Service 7e342f
 * @param [out] slabBlockNumberPtr      A pointer to the slab block number
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return VDO_SUCCESS or an error code
Packit Service 7e342f
 **/
Packit Service 7e342f
int slabBlockNumberFromPBN(Slab                *slab,
Packit Service 7e342f
                           PhysicalBlockNumber  physicalBlockNumber,
Packit Service 7e342f
                           SlabBlockNumber     *slabBlockNumberPtr)
Packit Service 7e342f
  __attribute__((warn_unused_result));
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Check whether the reference counts for a given rebuilt slab should be saved.
Packit Service 7e342f
 * Implements SlabStatusChecker.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab to check
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return true if the slab should be saved
Packit Service 7e342f
 **/
Packit Service 7e342f
bool shouldSaveFullyBuiltSlab(const Slab *slab)
Packit Service 7e342f
  __attribute__((warn_unused_result));
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Start an administrative operation on a slab.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab       The slab to load
Packit Service 7e342f
 * @param operation  The type of load to perform
Packit Service 7e342f
 * @param parent     The object to notify when the operation is complete
Packit Service 7e342f
 **/
Packit Service 7e342f
void startSlabAction(Slab           *slab,
Packit Service 7e342f
                     AdminStateCode  operation,
Packit Service 7e342f
                     VDOCompletion  *parent);
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Inform a slab that its journal has been loaded.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab    The slab whose journal has been loaded
Packit Service 7e342f
 * @param result  The result of the load operation
Packit Service 7e342f
 **/
Packit Service 7e342f
void notifySlabJournalIsLoaded(Slab *slab, int result);
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Check whether a slab is open, i.e. is neither quiescent nor quiescing.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab to check
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return true if the slab is open
Packit Service 7e342f
 **/
Packit Service 7e342f
bool isSlabOpen(Slab *slab)
Packit Service 7e342f
  __attribute__((warn_unused_result));
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Check whether a slab is currently draining.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab to check
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return true if the slab is performing a drain operation
Packit Service 7e342f
 **/
Packit Service 7e342f
bool isSlabDraining(Slab *slab)
Packit Service 7e342f
  __attribute__((warn_unused_result));
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Check whether a slab has drained, and if so, send a notification thereof.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab to check
Packit Service 7e342f
 **/
Packit Service 7e342f
void checkIfSlabDrained(Slab *slab);
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Inform a slab that its journal has finished draining.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab    The slab whose journal has been drained
Packit Service 7e342f
 * @param result  The result of the drain operation
Packit Service 7e342f
 **/
Packit Service 7e342f
void notifySlabJournalIsDrained(Slab *slab, int result);
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Inform a slab that its RefCounts have finished draining.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab    The slab whose RefCounts has been drained
Packit Service 7e342f
 * @param result  The result of the drain operation
Packit Service 7e342f
 **/
Packit Service 7e342f
void notifyRefCountsAreDrained(Slab *slab, int result);
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Check whether a slab is currently resuming.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab to check
Packit Service 7e342f
 *
Packit Service 7e342f
 * @return true if the slab is performing a resume operation
Packit Service 7e342f
 **/
Packit Service 7e342f
bool isSlabResuming(Slab *slab)
Packit Service 7e342f
  __attribute__((warn_unused_result));
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Finish scrubbing a slab now that it has been rebuilt by updating its status,
Packit Service 7e342f
 * queueing it for allocation, and reopening its journal.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab  The slab whose reference counts have been rebuilt from its
Packit Service 7e342f
 *              journal
Packit Service 7e342f
 **/
Packit Service 7e342f
void finishScrubbingSlab(Slab *slab);
Packit Service 7e342f
Packit Service 7e342f
/**
Packit Service 7e342f
 * Dump information about a slab to the log for debugging.
Packit Service 7e342f
 *
Packit Service 7e342f
 * @param slab   The slab to dump
Packit Service 7e342f
 **/
Packit Service 7e342f
void dumpSlab(const Slab *slab);
Packit Service 7e342f
Packit Service 7e342f
#endif // VDO_SLAB_H