Blame source/vdo/base/slab.c

Packit Service 75d76b
/*
Packit Service 75d76b
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service 75d76b
 *
Packit Service 75d76b
 * This program is free software; you can redistribute it and/or
Packit Service 75d76b
 * modify it under the terms of the GNU General Public License
Packit Service 75d76b
 * as published by the Free Software Foundation; either version 2
Packit Service 75d76b
 * of the License, or (at your option) any later version.
Packit Service 75d76b
 * 
Packit Service 75d76b
 * This program is distributed in the hope that it will be useful,
Packit Service 75d76b
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 75d76b
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 75d76b
 * GNU General Public License for more details.
Packit Service 75d76b
 * 
Packit Service 75d76b
 * You should have received a copy of the GNU General Public License
Packit Service 75d76b
 * along with this program; if not, write to the Free Software
Packit Service 75d76b
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 75d76b
 * 02110-1301, USA. 
Packit Service 75d76b
 *
Packit Service 75d76b
 * $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/slab.c#9 $
Packit Service 75d76b
 */
Packit Service 75d76b
Packit Service 75d76b
#include "slab.h"
Packit Service 75d76b
Packit Service 75d76b
#include "logger.h"
Packit Service 75d76b
#include "memoryAlloc.h"
Packit Service 75d76b
Packit Service 75d76b
#include "adminState.h"
Packit Service 75d76b
#include "blockAllocatorInternals.h"
Packit Service 75d76b
#include "completion.h"
Packit Service 75d76b
#include "constants.h"
Packit Service 75d76b
#include "numUtils.h"
Packit Service 75d76b
#include "pbnLock.h"
Packit Service 75d76b
#include "recoveryJournal.h"
Packit Service 75d76b
#include "refCounts.h"
Packit Service 75d76b
#include "slabDepot.h"
Packit Service 75d76b
#include "slabJournal.h"
Packit Service 75d76b
#include "slabJournalInternals.h"
Packit Service 75d76b
#include "slabSummary.h"
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
int configureSlab(BlockCount  slabSize,
Packit Service 75d76b
                  BlockCount  slabJournalBlocks,
Packit Service 75d76b
                  SlabConfig *slabConfig)
Packit Service 75d76b
{
Packit Service 75d76b
  if (slabJournalBlocks >= slabSize) {
Packit Service 75d76b
    return VDO_BAD_CONFIGURATION;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  /*
Packit Service 75d76b
   * This calculation should technically be a recurrence, but the total number
Packit Service 75d76b
   * of metadata blocks is currently less than a single block of refCounts, so
Packit Service 75d76b
   * we'd gain at most one data block in each slab with more iteration.
Packit Service 75d76b
   */
Packit Service 75d76b
  BlockCount refBlocks
Packit Service 75d76b
    = getSavedReferenceCountSize(slabSize - slabJournalBlocks);
Packit Service 75d76b
  BlockCount metaBlocks = (refBlocks + slabJournalBlocks);
Packit Service 75d76b
Packit Service 75d76b
  // Make sure test code hasn't configured slabs to be too small.
Packit Service 75d76b
  if (metaBlocks >= slabSize) {
Packit Service 75d76b
    return VDO_BAD_CONFIGURATION;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  /*
Packit Service 75d76b
   * If the slab size is very small, assume this must be a unit test and
Packit Service 75d76b
   * override the number of data blocks to be a power of two (wasting blocks
Packit Service 75d76b
   * in the slab). Many tests need their dataBlocks fields to be the exact
Packit Service 75d76b
   * capacity of the configured volume, and that used to fall out since they
Packit Service 75d76b
   * use a power of two for the number of data blocks, the slab size was a
Packit Service 75d76b
   * power of two, and every block in a slab was a data block.
Packit Service 75d76b
   *
Packit Service 75d76b
   * XXX Try to figure out some way of structuring testParameters and unit
Packit Service 75d76b
   * tests so this hack isn't needed without having to edit several unit tests
Packit Service 75d76b
   * every time the metadata size changes by one block.
Packit Service 75d76b
   */
Packit Service 75d76b
  BlockCount dataBlocks = slabSize - metaBlocks;
Packit Service 75d76b
  if ((slabSize < 1024) && !isPowerOfTwo(dataBlocks)) {
Packit Service 75d76b
    dataBlocks = ((BlockCount) 1 << logBaseTwo(dataBlocks));
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  /*
Packit Service 75d76b
   * Configure the slab journal thresholds. The flush threshold is 168 of 224
Packit Service 75d76b
   * blocks in production, or 3/4ths, so we use this ratio for all sizes.
Packit Service 75d76b
   */
Packit Service 75d76b
  BlockCount flushingThreshold = ((slabJournalBlocks * 3) + 3) / 4;
Packit Service 75d76b
  /*
Packit Service 75d76b
   * The blocking threshold should be far enough from the the flushing
Packit Service 75d76b
   * threshold to not produce delays, but far enough from the end of the
Packit Service 75d76b
   * journal to allow multiple successive recovery failures.
Packit Service 75d76b
   */
Packit Service 75d76b
  BlockCount remaining = slabJournalBlocks - flushingThreshold;
Packit Service 75d76b
  BlockCount blockingThreshold = flushingThreshold + ((remaining * 5) / 7);
Packit Service 75d76b
  /*
Packit Service 75d76b
   * The scrubbing threshold should be at least 2048 entries before the end of
Packit Service 75d76b
   * the journal.
Packit Service 75d76b
   */
Packit Service 75d76b
  BlockCount minimalExtraSpace
Packit Service 75d76b
    = 1 + (MAXIMUM_USER_VIOS / SLAB_JOURNAL_FULL_ENTRIES_PER_BLOCK);
Packit Service 75d76b
  BlockCount scrubbingThreshold = blockingThreshold;
Packit Service 75d76b
  if (slabJournalBlocks > minimalExtraSpace) {
Packit Service 75d76b
    scrubbingThreshold = slabJournalBlocks - minimalExtraSpace;
Packit Service 75d76b
  }
Packit Service 75d76b
  if (blockingThreshold > scrubbingThreshold) {
Packit Service 75d76b
    blockingThreshold = scrubbingThreshold;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  *slabConfig = (SlabConfig) {
Packit Service 75d76b
    .slabBlocks                    = slabSize,
Packit Service 75d76b
    .dataBlocks                    = dataBlocks,
Packit Service 75d76b
    .referenceCountBlocks          = refBlocks,
Packit Service 75d76b
    .slabJournalBlocks             = slabJournalBlocks,
Packit Service 75d76b
    .slabJournalFlushingThreshold  = flushingThreshold,
Packit Service 75d76b
    .slabJournalBlockingThreshold  = blockingThreshold,
Packit Service 75d76b
    .slabJournalScrubbingThreshold = scrubbingThreshold
Packit Service 75d76b
  };
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
PhysicalBlockNumber getSlabJournalStartBlock(const SlabConfig    *slabConfig,
Packit Service 75d76b
                                             PhysicalBlockNumber  origin)
Packit Service 75d76b
{
Packit Service 75d76b
  return origin + slabConfig->dataBlocks + slabConfig->referenceCountBlocks;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
int makeSlab(PhysicalBlockNumber   slabOrigin,
Packit Service 75d76b
             BlockAllocator       *allocator,
Packit Service 75d76b
             PhysicalBlockNumber   translation,
Packit Service 75d76b
             RecoveryJournal      *recoveryJournal,
Packit Service 75d76b
             SlabCount             slabNumber,
Packit Service 75d76b
             bool                  isNew,
Packit Service 75d76b
             Slab                **slabPtr)
Packit Service 75d76b
{
Packit Service 75d76b
  Slab *slab;
Packit Service 75d76b
  int result = ALLOCATE(1, Slab, __func__, &slab;;
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  const SlabConfig *slabConfig = getSlabConfig(allocator->depot);
Packit Service 75d76b
Packit Service 75d76b
  slab->allocator  = allocator;
Packit Service 75d76b
  slab->start      = slabOrigin;
Packit Service 75d76b
  slab->end        = slab->start + slabConfig->slabBlocks;
Packit Service 75d76b
  slab->slabNumber = slabNumber;
Packit Service 75d76b
  initializeRing(&slab->ringNode);
Packit Service 75d76b
Packit Service 75d76b
  slab->refCountsOrigin = slabOrigin + slabConfig->dataBlocks + translation;
Packit Service 75d76b
  slab->journalOrigin   = (getSlabJournalStartBlock(slabConfig, slabOrigin)
Packit Service 75d76b
                           + translation);
Packit Service 75d76b
Packit Service 75d76b
  result = makeSlabJournal(allocator, slab, recoveryJournal, &slab->journal);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    freeSlab(&slab;;
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  if (isNew) {
Packit Service 75d76b
    slab->state.state = ADMIN_STATE_NEW;
Packit Service 75d76b
    result = allocateRefCountsForSlab(slab);
Packit Service 75d76b
    if (result != VDO_SUCCESS) {
Packit Service 75d76b
      freeSlab(&slab;;
Packit Service 75d76b
      return result;
Packit Service 75d76b
    }
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  *slabPtr = slab;
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
int allocateRefCountsForSlab(Slab *slab)
Packit Service 75d76b
{
Packit Service 75d76b
  BlockAllocator   *allocator  = slab->allocator;
Packit Service 75d76b
  const SlabConfig *slabConfig = getSlabConfig(allocator->depot);
Packit Service 75d76b
Packit Service 75d76b
  int result = ASSERT(slab->referenceCounts == NULL,
Packit Service 75d76b
                      "Slab %u doesn't allocate refcounts twice",
Packit Service 75d76b
                      slab->slabNumber);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  return makeRefCounts(slabConfig->dataBlocks, slab, slab->refCountsOrigin,
Packit Service 75d76b
                       allocator->readOnlyNotifier, &slab->referenceCounts);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
void freeSlab(Slab **slabPtr)
Packit Service 75d76b
{
Packit Service 75d76b
  Slab *slab = *slabPtr;
Packit Service 75d76b
  if (slab == NULL) {
Packit Service 75d76b
    return;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  unspliceRingNode(&slab->ringNode);
Packit Service 75d76b
  freeSlabJournal(&slab->journal);
Packit Service 75d76b
  freeRefCounts(&slab->referenceCounts);
Packit Service 75d76b
  FREE(slab);
Packit Service 75d76b
  *slabPtr = NULL;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
ZoneCount getSlabZoneNumber(Slab *slab)
Packit Service 75d76b
{
Packit Service 75d76b
  return slab->allocator->zoneNumber;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
void markSlabReplaying(Slab *slab)
Packit Service 75d76b
{
Packit Service 75d76b
  if (slab->status == SLAB_REBUILT) {
Packit Service 75d76b
    slab->status = SLAB_REPLAYING;
Packit Service 75d76b
  }
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
void markSlabUnrecovered(Slab *slab)
Packit Service 75d76b
{
Packit Service 75d76b
  slab->status = SLAB_REQUIRES_SCRUBBING;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
BlockCount getSlabFreeBlockCount(const Slab *slab)
Packit Service 75d76b
{
Packit Service 75d76b
  return getUnreferencedBlockCount(slab->referenceCounts);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
int modifySlabReferenceCount(Slab               *slab,
Packit Service 75d76b
                             const JournalPoint *journalPoint,
Packit Service 75d76b
                             ReferenceOperation  operation)
Packit Service 75d76b
{
Packit Service 75d76b
  if (slab == NULL) {
Packit Service 75d76b
    return VDO_SUCCESS;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  /*
Packit Service 75d76b
   * If the slab is unrecovered, preserve the refCount state and let scrubbing
Packit Service 75d76b
   * correct the refCount. Note that the slab journal has already captured all
Packit Service 75d76b
   * refCount updates.
Packit Service 75d76b
   */
Packit Service 75d76b
  if (isUnrecoveredSlab(slab)) {
Packit Service 75d76b
    SequenceNumber entryLock = journalPoint->sequenceNumber;
Packit Service 75d76b
    adjustSlabJournalBlockReference(slab->journal, entryLock, -1);
Packit Service 75d76b
    return VDO_SUCCESS;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  bool freeStatusChanged;
Packit Service 75d76b
  int result = adjustReferenceCount(slab->referenceCounts, operation,
Packit Service 75d76b
                                    journalPoint, &freeStatusChanged);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  if (freeStatusChanged) {
Packit Service 75d76b
    adjustFreeBlockCount(slab, !isIncrementOperation(operation.type));
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
int acquireProvisionalReference(Slab                *slab,
Packit Service 75d76b
                                PhysicalBlockNumber  pbn,
Packit Service 75d76b
                                PBNLock             *lock)
Packit Service 75d76b
{
Packit Service 75d76b
  if (hasProvisionalReference(lock)) {
Packit Service 75d76b
    return VDO_SUCCESS;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  int result = provisionallyReferenceBlock(slab->referenceCounts, pbn, lock);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  if (hasProvisionalReference(lock)) {
Packit Service 75d76b
    adjustFreeBlockCount(slab, false);
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
int slabBlockNumberFromPBN(Slab                *slab,
Packit Service 75d76b
                           PhysicalBlockNumber  physicalBlockNumber,
Packit Service 75d76b
                           SlabBlockNumber     *slabBlockNumberPtr)
Packit Service 75d76b
{
Packit Service 75d76b
  if (physicalBlockNumber < slab->start) {
Packit Service 75d76b
    return VDO_OUT_OF_RANGE;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  uint64_t slabBlockNumber = physicalBlockNumber - slab->start;
Packit Service 75d76b
  if (slabBlockNumber >= getSlabConfig(slab->allocator->depot)->dataBlocks) {
Packit Service 75d76b
    return VDO_OUT_OF_RANGE;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  *slabBlockNumberPtr = slabBlockNumber;
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
bool shouldSaveFullyBuiltSlab(const Slab *slab)
Packit Service 75d76b
{
Packit Service 75d76b
  // Write out the refCounts if the slab has written them before, or it has
Packit Service 75d76b
  // any non-zero reference counts, or there are any slab journal blocks.
Packit Service 75d76b
  BlockCount dataBlocks = getSlabConfig(slab->allocator->depot)->dataBlocks;
Packit Service 75d76b
  return (mustLoadRefCounts(slab->allocator->summary, slab->slabNumber)
Packit Service 75d76b
          || (getSlabFreeBlockCount(slab) != dataBlocks)
Packit Service 75d76b
          || !isSlabJournalBlank(slab->journal));
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Initiate a slab action.
Packit Service 75d76b
 *
Packit Service 75d76b
 * Implements AdminInitiator.
Packit Service 75d76b
 **/
Packit Service 75d76b
static void initiateSlabAction(AdminState *state)
Packit Service 75d76b
{
Packit Service 75d76b
  Slab *slab = container_of(state, Slab, state);
Packit Service 75d76b
  if (isDraining(state)) {
Packit Service 75d76b
    if (state->state == ADMIN_STATE_SCRUBBING) {
Packit Service 75d76b
      slab->status = SLAB_REBUILDING;
Packit Service 75d76b
    }
Packit Service 75d76b
Packit Service 75d76b
    drainSlabJournal(slab->journal);
Packit Service 75d76b
Packit Service 75d76b
    if (slab->referenceCounts != NULL) {
Packit Service 75d76b
      drainRefCounts(slab->referenceCounts);
Packit Service 75d76b
    }
Packit Service 75d76b
Packit Service 75d76b
    checkIfSlabDrained(slab);
Packit Service 75d76b
    return;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  if (isLoading(state)) {
Packit Service 75d76b
    decodeSlabJournal(slab->journal);
Packit Service 75d76b
    return;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  if (isResuming(state)) {
Packit Service 75d76b
    queueSlab(slab);
Packit Service 75d76b
    finishResuming(state);
Packit Service 75d76b
    return;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  finishOperationWithResult(state, VDO_INVALID_ADMIN_STATE);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
void startSlabAction(Slab           *slab,
Packit Service 75d76b
                     AdminStateCode  operation,
Packit Service 75d76b
                     VDOCompletion  *parent)
Packit Service 75d76b
{
Packit Service 75d76b
  startOperationWithWaiter(&slab->state, operation, parent,
Packit Service 75d76b
                           initiateSlabAction);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
void notifySlabJournalIsLoaded(Slab *slab, int result)
Packit Service 75d76b
{
Packit Service 75d76b
  if ((result == VDO_SUCCESS) && isCleanLoad(&slab->state)) {
Packit Service 75d76b
    // Since this is a normal or new load, we don't need the memory to read and
Packit Service 75d76b
    // process the recovery journal, so we can allocate reference counts now.
Packit Service 75d76b
    result = allocateRefCountsForSlab(slab);
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  finishLoadingWithResult(&slab->state, result);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
bool isSlabOpen(Slab *slab)
Packit Service 75d76b
{
Packit Service 75d76b
  return (!isQuiescing(&slab->state) && !isQuiescent(&slab->state));
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
bool isSlabDraining(Slab *slab)
Packit Service 75d76b
{
Packit Service 75d76b
  return isDraining(&slab->state);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
void checkIfSlabDrained(Slab *slab)
Packit Service 75d76b
{
Packit Service 75d76b
  if (isDraining(&slab->state)
Packit Service 75d76b
      && !isSlabJournalActive(slab->journal)
Packit Service 75d76b
      && ((slab->referenceCounts == NULL)
Packit Service 75d76b
          || !areRefCountsActive(slab->referenceCounts))) {
Packit Service 75d76b
    finishDrainingWithResult(&slab->state,
Packit Service 75d76b
                             (isReadOnly(slab->allocator->readOnlyNotifier)
Packit Service 75d76b
                              ? VDO_READ_ONLY : VDO_SUCCESS));
Packit Service 75d76b
  }
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
void notifySlabJournalIsDrained(Slab *slab, int result)
Packit Service 75d76b
{
Packit Service 75d76b
  if (slab->referenceCounts == NULL) {
Packit Service 75d76b
    // This can happen when shutting down a VDO that was in read-only mode when
Packit Service 75d76b
    // loaded.
Packit Service 75d76b
    notifyRefCountsAreDrained(slab, result);
Packit Service 75d76b
    return;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  setOperationResult(&slab->state, result);
Packit Service 75d76b
  drainRefCounts(slab->referenceCounts);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
void notifyRefCountsAreDrained(Slab *slab, int result)
Packit Service 75d76b
{
Packit Service 75d76b
  finishDrainingWithResult(&slab->state, result);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
bool isSlabResuming(Slab *slab)
Packit Service 75d76b
{
Packit Service 75d76b
  return isResuming(&slab->state);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
void finishScrubbingSlab(Slab *slab)
Packit Service 75d76b
{
Packit Service 75d76b
  slab->status = SLAB_REBUILT;
Packit Service 75d76b
  queueSlab(slab);
Packit Service 75d76b
  reopenSlabJournal(slab->journal);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
static const char *statusToString(SlabRebuildStatus status)
Packit Service 75d76b
{
Packit Service 75d76b
  switch (status) {
Packit Service 75d76b
  case SLAB_REBUILT:
Packit Service 75d76b
    return "REBUILT";
Packit Service 75d76b
  case SLAB_REQUIRES_SCRUBBING:
Packit Service 75d76b
    return "SCRUBBING";
Packit Service 75d76b
  case SLAB_REQUIRES_HIGH_PRIORITY_SCRUBBING:
Packit Service 75d76b
    return "PRIORITY_SCRUBBING";
Packit Service 75d76b
  case SLAB_REBUILDING:
Packit Service 75d76b
    return "REBUILDING";
Packit Service 75d76b
  case SLAB_REPLAYING:
Packit Service 75d76b
    return "REPLAYING";
Packit Service 75d76b
  default:
Packit Service 75d76b
    return "UNKNOWN";
Packit Service 75d76b
  }
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
void dumpSlab(const Slab *slab)
Packit Service 75d76b
{
Packit Service 75d76b
  if (slab->referenceCounts != NULL) {
Packit Service 75d76b
    // Terse because there are a lot of slabs to dump and syslog is lossy.
Packit Service 75d76b
    logInfo("slab %u: P%u, %llu free",
Packit Service 75d76b
            slab->slabNumber, slab->priority, getSlabFreeBlockCount(slab));
Packit Service 75d76b
  } else {
Packit Service 75d76b
    logInfo("slab %u: status %s", slab->slabNumber,
Packit Service 75d76b
            statusToString(slab->status));
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  dumpSlabJournal(slab->journal);
Packit Service 75d76b
Packit Service 75d76b
  if (slab->referenceCounts != NULL) {
Packit Service 75d76b
    dumpRefCounts(slab->referenceCounts);
Packit Service 75d76b
  } else {
Packit Service 75d76b
    logInfo("refCounts is null");
Packit Service 75d76b
  }
Packit Service 75d76b
}