Blame source/vdo/base/readOnlyRebuild.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/readOnlyRebuild.c#9 $
Packit Service 75d76b
 */
Packit Service 75d76b
Packit Service 75d76b
#include "readOnlyRebuild.h"
Packit Service 75d76b
Packit Service 75d76b
#include "logger.h"
Packit Service 75d76b
#include "memoryAlloc.h"
Packit Service 75d76b
Packit Service 75d76b
#include "blockMapInternals.h"
Packit Service 75d76b
#include "blockMapRecovery.h"
Packit Service 75d76b
#include "completion.h"
Packit Service 75d76b
#include "numUtils.h"
Packit Service 75d76b
#include "packedRecoveryJournalBlock.h"
Packit Service 75d76b
#include "recoveryJournalInternals.h"
Packit Service 75d76b
#include "recoveryUtils.h"
Packit Service 75d76b
#include "referenceCountRebuild.h"
Packit Service 75d76b
#include "slabDepot.h"
Packit Service 75d76b
#include "vdoInternal.h"
Packit Service 75d76b
#include "vdoPageCache.h"
Packit Service 75d76b
Packit Service 75d76b
typedef struct {
Packit Service 75d76b
  /** The completion header */
Packit Service 75d76b
  VDOCompletion         completion;
Packit Service 75d76b
  /** A sub task completion */
Packit Service 75d76b
  VDOCompletion         subTaskCompletion;
Packit Service 75d76b
  /** The VDO in question */
Packit Service 75d76b
  VDO                  *vdo;
Packit Service 75d76b
  /** A buffer to hold the data read off disk */
Packit Service 75d76b
  char                 *journalData;
Packit Service 75d76b
  /** The entry data for the block map rebuild */
Packit Service 75d76b
  NumberedBlockMapping *entries;
Packit Service 75d76b
  /** The number of entries in the entry array */
Packit Service 75d76b
  size_t                entryCount;
Packit Service 75d76b
  /** The sequence number of the first valid block of the journal (if known) */
Packit Service 75d76b
  SequenceNumber        head;
Packit Service 75d76b
  /** The sequence number of the last valid block of the journal (if known) */
Packit Service 75d76b
  SequenceNumber        tail;
Packit Service 75d76b
  /** The number of logical blocks in use */
Packit Service 75d76b
  BlockCount            logicalBlocksUsed;
Packit Service 75d76b
  /** The number of allocated block map pages */
Packit Service 75d76b
  BlockCount            blockMapDataBlocks;
Packit Service 75d76b
} ReadOnlyRebuildCompletion;
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Convert a generic completion to a ReadOnlyRebuildCompletion.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion    The completion to convert
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return the journal rebuild completion
Packit Service 75d76b
 **/
Packit Service 75d76b
__attribute__((warn_unused_result))
Packit Service 75d76b
static inline ReadOnlyRebuildCompletion *
Packit Service 75d76b
asReadOnlyRebuildCompletion(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  STATIC_ASSERT(offsetof(ReadOnlyRebuildCompletion, completion) == 0);
Packit Service 75d76b
  assertCompletionType(completion->type, READ_ONLY_REBUILD_COMPLETION);
Packit Service 75d76b
  return (ReadOnlyRebuildCompletion *) completion;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Free a rebuild completion and all underlying structures.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param rebuildPtr  A pointer to the rebuild completion to free
Packit Service 75d76b
 */
Packit Service 75d76b
static void freeRebuildCompletion(ReadOnlyRebuildCompletion **rebuildPtr)
Packit Service 75d76b
{
Packit Service 75d76b
  ReadOnlyRebuildCompletion *rebuild = *rebuildPtr;
Packit Service 75d76b
  if (rebuild == NULL) {
Packit Service 75d76b
    return;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  destroyEnqueueable(&rebuild->subTaskCompletion);
Packit Service 75d76b
  FREE(rebuild->journalData);
Packit Service 75d76b
  FREE(rebuild->entries);
Packit Service 75d76b
  FREE(rebuild);
Packit Service 75d76b
  *rebuildPtr = NULL;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Allocate and initialize a read only rebuild completion.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param [in]  vdo         The VDO in question
Packit Service 75d76b
 * @param [out] rebuildPtr  A pointer to return the created rebuild completion
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return VDO_SUCCESS or an error code
Packit Service 75d76b
 **/
Packit Service 75d76b
static int makeRebuildCompletion(VDO                        *vdo,
Packit Service 75d76b
                                 ReadOnlyRebuildCompletion **rebuildPtr)
Packit Service 75d76b
{
Packit Service 75d76b
  ReadOnlyRebuildCompletion *rebuild;
Packit Service 75d76b
  int result = ALLOCATE(1, ReadOnlyRebuildCompletion, __func__, &rebuild);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  initializeCompletion(&rebuild->completion, READ_ONLY_REBUILD_COMPLETION,
Packit Service 75d76b
                       vdo->layer);
Packit Service 75d76b
Packit Service 75d76b
  result = initializeEnqueueableCompletion(&rebuild->subTaskCompletion,
Packit Service 75d76b
                                           SUB_TASK_COMPLETION, vdo->layer);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    freeRebuildCompletion(&rebuild);
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  rebuild->vdo = vdo;
Packit Service 75d76b
  *rebuildPtr = rebuild;
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Clean up the rebuild process, whether or not it succeeded, by freeing the
Packit Service 75d76b
 * rebuild completion and notifying the parent of the outcome.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The rebuild completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void completeRebuild(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  VDOCompletion             *parent  = completion->parent;
Packit Service 75d76b
  int                        result  = completion->result;
Packit Service 75d76b
  ReadOnlyRebuildCompletion *rebuild = asReadOnlyRebuildCompletion(completion);
Packit Service 75d76b
  VDO                       *vdo     = rebuild->vdo;
Packit Service 75d76b
  setVDOPageCacheRebuildMode(getBlockMap(vdo)->zones[0].pageCache, false);
Packit Service 75d76b
  freeRebuildCompletion(&rebuild);
Packit Service 75d76b
  finishCompletion(parent, result);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Finish rebuilding, free the rebuild completion and notify the parent.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The rebuild completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void finishRebuild(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  ReadOnlyRebuildCompletion *rebuild = asReadOnlyRebuildCompletion(completion);
Packit Service 75d76b
  initializeRecoveryJournalPostRebuild(rebuild->vdo->recoveryJournal,
Packit Service 75d76b
                                       rebuild->vdo->completeRecoveries,
Packit Service 75d76b
                                       rebuild->tail,
Packit Service 75d76b
                                       rebuild->logicalBlocksUsed,
Packit Service 75d76b
                                       rebuild->blockMapDataBlocks);
Packit Service 75d76b
  logInfo("Read-only rebuild complete");
Packit Service 75d76b
  completeRebuild(completion);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Handle a rebuild error.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The rebuild completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void abortRebuild(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  logInfo("Read-only rebuild aborted");
Packit Service 75d76b
  completeRebuild(completion);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Abort a rebuild if there is an error.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param result   The result to check
Packit Service 75d76b
 * @param rebuild  The journal rebuild completion
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return true if the result was an error
Packit Service 75d76b
 **/
Packit Service 75d76b
__attribute__((warn_unused_result))
Packit Service 75d76b
static bool abortRebuildOnError(int                        result,
Packit Service 75d76b
                                ReadOnlyRebuildCompletion *rebuild)
Packit Service 75d76b
{
Packit Service 75d76b
  if (result == VDO_SUCCESS) {
Packit Service 75d76b
    return false;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  finishCompletion(&rebuild->completion, result);
Packit Service 75d76b
  return true;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Clean up after finishing the reference count rebuild. This callback is
Packit Service 75d76b
 * registered in launchReferenceCountRebuild().
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void finishReferenceCountRebuild(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  ReadOnlyRebuildCompletion *rebuild = completion->parent;
Packit Service 75d76b
  VDO                       *vdo     = rebuild->vdo;
Packit Service 75d76b
  assertOnAdminThread(vdo, __func__);
Packit Service 75d76b
  if (vdo->loadState != VDO_REBUILD_FOR_UPGRADE) {
Packit Service 75d76b
    // A "rebuild" for upgrade should not increment this count.
Packit Service 75d76b
    vdo->completeRecoveries++;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  logInfo("Saving rebuilt state");
Packit Service 75d76b
  prepareToFinishParent(completion, &rebuild->completion);
Packit Service 75d76b
  drainSlabDepot(vdo->depot, ADMIN_STATE_REBUILDING, completion);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Rebuild the reference counts from the block map now that all journal entries
Packit Service 75d76b
 * have been applied to the block map. This callback is registered in
Packit Service 75d76b
 * applyJournalEntries().
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void launchReferenceCountRebuild(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  ReadOnlyRebuildCompletion *rebuild = completion->parent;
Packit Service 75d76b
  VDO                       *vdo     = rebuild->vdo;
Packit Service 75d76b
Packit Service 75d76b
  // We must allocate RefCounts before we can rebuild them.
Packit Service 75d76b
  int result = allocateSlabRefCounts(vdo->depot);
Packit Service 75d76b
  if (abortRebuildOnError(result, rebuild)) {
Packit Service 75d76b
    return;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  prepareCompletion(completion, finishReferenceCountRebuild,
Packit Service 75d76b
                    finishParentCallback, getAdminThread(getThreadConfig(vdo)),
Packit Service 75d76b
                    completion->parent);
Packit Service 75d76b
  rebuildReferenceCounts(vdo, completion, &rebuild->logicalBlocksUsed,
Packit Service 75d76b
                         &rebuild->blockMapDataBlocks);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Append an array of recovery journal entries from a journal block sector to
Packit Service 75d76b
 * the array of numbered mappings in the rebuild completion, numbering each
Packit Service 75d76b
 * entry in the order they are appended.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param rebuild     The journal rebuild completion
Packit Service 75d76b
 * @param sector      The recovery journal sector with entries
Packit Service 75d76b
 * @param entryCount  The number of entries to append
Packit Service 75d76b
 **/
Packit Service 75d76b
static void appendSectorEntries(ReadOnlyRebuildCompletion *rebuild,
Packit Service 75d76b
                                PackedJournalSector       *sector,
Packit Service 75d76b
                                JournalEntryCount          entryCount)
Packit Service 75d76b
{
Packit Service 75d76b
  for (JournalEntryCount i = 0; i < entryCount; i++) {
Packit Service 75d76b
    RecoveryJournalEntry entry
Packit Service 75d76b
      = unpackRecoveryJournalEntry(&sector->entries[i]);
Packit Service 75d76b
    int result = validateRecoveryJournalEntry(rebuild->vdo, &entry);
Packit Service 75d76b
    if (result != VDO_SUCCESS) {
Packit Service 75d76b
      // When recovering from read-only mode, ignore damaged entries.
Packit Service 75d76b
      continue;
Packit Service 75d76b
    }
Packit Service 75d76b
Packit Service 75d76b
    if (isIncrementOperation(entry.operation)) {
Packit Service 75d76b
      rebuild->entries[rebuild->entryCount] = (NumberedBlockMapping) {
Packit Service 75d76b
        .blockMapSlot  = entry.slot,
Packit Service 75d76b
        .blockMapEntry = packPBN(entry.mapping.pbn, entry.mapping.state),
Packit Service 75d76b
        .number        = rebuild->entryCount,
Packit Service 75d76b
      };
Packit Service 75d76b
      rebuild->entryCount++;
Packit Service 75d76b
    }
Packit Service 75d76b
  }
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Create an array of all valid journal entries, in order, and store
Packit Service 75d76b
 * it in the rebuild completion.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param rebuild  The journal rebuild completion
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return VDO_SUCCESS or an error code
Packit Service 75d76b
 **/
Packit Service 75d76b
static int extractJournalEntries(ReadOnlyRebuildCompletion *rebuild)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO             *vdo      = rebuild->vdo;
Packit Service 75d76b
  RecoveryJournal *journal  = vdo->recoveryJournal;
Packit Service 75d76b
  SequenceNumber   first    = rebuild->head;
Packit Service 75d76b
  SequenceNumber   last     = rebuild->tail;
Packit Service 75d76b
  BlockCount       maxCount = ((last - first + 1) * journal->entriesPerBlock);
Packit Service 75d76b
Packit Service 75d76b
  // Allocate a NumberedBlockMapping array large enough to transcribe every
Packit Service 75d76b
  // PackedRecoveryJournalEntry from every valid journal block.
Packit Service 75d76b
  int result = ALLOCATE(maxCount, NumberedBlockMapping, __func__,
Packit Service 75d76b
                        &rebuild->entries);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  for (SequenceNumber i = first; i <= last; i++) {
Packit Service 75d76b
    PackedJournalHeader *packedHeader
Packit Service 75d76b
      = getJournalBlockHeader(journal, rebuild->journalData, i);
Packit Service 75d76b
    RecoveryBlockHeader header;
Packit Service 75d76b
    unpackRecoveryBlockHeader(packedHeader, &header);
Packit Service 75d76b
Packit Service 75d76b
    if (!isExactRecoveryJournalBlock(journal, &header, i)) {
Packit Service 75d76b
      // This block is invalid, so skip it.
Packit Service 75d76b
      continue;
Packit Service 75d76b
    }
Packit Service 75d76b
Packit Service 75d76b
    // Don't extract more than the expected maximum entries per block.
Packit Service 75d76b
    JournalEntryCount blockEntries = minBlock(journal->entriesPerBlock,
Packit Service 75d76b
                                              header.entryCount);
Packit Service 75d76b
    for (uint8_t j = 1; j < SECTORS_PER_BLOCK; j++) {
Packit Service 75d76b
      // Stop when all entries counted in the header are applied or skipped.
Packit Service 75d76b
      if (blockEntries == 0) {
Packit Service 75d76b
        break;
Packit Service 75d76b
      }
Packit Service 75d76b
Packit Service 75d76b
      PackedJournalSector *sector = getJournalBlockSector(packedHeader, j);
Packit Service 75d76b
      if (!isValidRecoveryJournalSector(&header, sector)) {
Packit Service 75d76b
        blockEntries -= minBlock(blockEntries,
Packit Service 75d76b
                                 RECOVERY_JOURNAL_ENTRIES_PER_SECTOR);
Packit Service 75d76b
        continue;
Packit Service 75d76b
      }
Packit Service 75d76b
Packit Service 75d76b
      // Don't extract more than the expected maximum entries per sector.
Packit Service 75d76b
      JournalEntryCount sectorEntries
Packit Service 75d76b
        = minBlock(sector->entryCount, RECOVERY_JOURNAL_ENTRIES_PER_SECTOR);
Packit Service 75d76b
      // Only extract as many as the block header calls for.
Packit Service 75d76b
      sectorEntries = minBlock(sectorEntries, blockEntries);
Packit Service 75d76b
      appendSectorEntries(rebuild, sector, sectorEntries);
Packit Service 75d76b
      // Even if the sector wasn't full, count it as full when counting up
Packit Service 75d76b
      // to the entry count the block header claims.
Packit Service 75d76b
      blockEntries -= minBlock(blockEntries,
Packit Service 75d76b
                               RECOVERY_JOURNAL_ENTRIES_PER_SECTOR);
Packit Service 75d76b
    }
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Determine the limits of the valid recovery journal and apply all
Packit Service 75d76b
 * valid entries to the block map. This callback is registered in
Packit Service 75d76b
 * rebuildJournalAsync().
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion   The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void applyJournalEntries(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  ReadOnlyRebuildCompletion *rebuild
Packit Service 75d76b
    = asReadOnlyRebuildCompletion(completion->parent);
Packit Service 75d76b
  VDO *vdo = rebuild->vdo;
Packit Service 75d76b
Packit Service 75d76b
  logInfo("Finished reading recovery journal");
Packit Service 75d76b
  assertOnLogicalZoneThread(vdo, 0, __func__);
Packit Service 75d76b
Packit Service 75d76b
  bool foundEntries = findHeadAndTail(vdo->recoveryJournal,
Packit Service 75d76b
                                     rebuild->journalData, &rebuild->tail,
Packit Service 75d76b
                                     &rebuild->head, NULL);
Packit Service 75d76b
  if (foundEntries) {
Packit Service 75d76b
    int result = extractJournalEntries(rebuild);
Packit Service 75d76b
    if (abortRebuildOnError(result, rebuild)) {
Packit Service 75d76b
      return;
Packit Service 75d76b
    }
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  // Suppress block map errors.
Packit Service 75d76b
  setVDOPageCacheRebuildMode(getBlockMap(vdo)->zones[0].pageCache, true);
Packit Service 75d76b
Packit Service 75d76b
  // Play the recovery journal into the block map.
Packit Service 75d76b
  prepareCompletion(completion, launchReferenceCountRebuild,
Packit Service 75d76b
                    finishParentCallback, completion->callbackThreadID,
Packit Service 75d76b
                    completion->parent);
Packit Service 75d76b
  recoverBlockMap(vdo, rebuild->entryCount, rebuild->entries, completion);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Begin loading the journal.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion    The sub task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void loadJournal(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  ReadOnlyRebuildCompletion *rebuild
Packit Service 75d76b
    = asReadOnlyRebuildCompletion(completion->parent);
Packit Service 75d76b
  VDO *vdo = rebuild->vdo;
Packit Service 75d76b
  assertOnLogicalZoneThread(vdo, 0, __func__);
Packit Service 75d76b
Packit Service 75d76b
  prepareCompletion(completion, applyJournalEntries, finishParentCallback,
Packit Service 75d76b
                    completion->callbackThreadID, completion->parent);
Packit Service 75d76b
  loadJournalAsync(vdo->recoveryJournal, completion, &rebuild->journalData);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
void launchRebuild(VDO *vdo, VDOCompletion *parent)
Packit Service 75d76b
{
Packit Service 75d76b
  // Note: These messages must be recognizable by Permabit::VDODeviceBase.
Packit Service 75d76b
  if (vdo->loadState == VDO_REBUILD_FOR_UPGRADE) {
Packit Service 75d76b
    logWarning("Rebuilding reference counts for upgrade");
Packit Service 75d76b
  } else {
Packit Service 75d76b
    logWarning("Rebuilding reference counts to clear read-only mode");
Packit Service 75d76b
    vdo->readOnlyRecoveries++;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  ReadOnlyRebuildCompletion *rebuild;
Packit Service 75d76b
  int result = makeRebuildCompletion(vdo, &rebuild);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    finishCompletion(parent, result);
Packit Service 75d76b
    return;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  VDOCompletion *completion = &rebuild->completion;
Packit Service 75d76b
  prepareCompletion(completion, finishRebuild, abortRebuild,
Packit Service 75d76b
                    parent->callbackThreadID, parent);
Packit Service 75d76b
Packit Service 75d76b
  VDOCompletion *subTaskCompletion = &rebuild->subTaskCompletion;
Packit Service 75d76b
  prepareCompletion(subTaskCompletion, loadJournal, finishParentCallback,
Packit Service 75d76b
                    getLogicalZoneThread(getThreadConfig(vdo), 0),
Packit Service 75d76b
                    completion);
Packit Service 75d76b
  loadSlabDepot(vdo->depot, ADMIN_STATE_LOADING_FOR_REBUILD,
Packit Service 75d76b
                subTaskCompletion, NULL);
Packit Service 75d76b
}