Blame source/vdo/base/vdoLoad.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/vdoLoad.c#17 $
Packit Service 75d76b
 */
Packit Service 75d76b
Packit Service 75d76b
#include "vdoLoad.h"
Packit Service 75d76b
Packit Service 75d76b
#include "logger.h"
Packit Service 75d76b
#include "memoryAlloc.h"
Packit Service 75d76b
Packit Service 75d76b
#include "adminCompletion.h"
Packit Service 75d76b
#include "blockMap.h"
Packit Service 75d76b
#include "completion.h"
Packit Service 75d76b
#include "constants.h"
Packit Service 75d76b
#include "hashZone.h"
Packit Service 75d76b
#include "header.h"
Packit Service 75d76b
#include "logicalZone.h"
Packit Service 75d76b
#include "physicalZone.h"
Packit Service 75d76b
#include "readOnlyRebuild.h"
Packit Service 75d76b
#include "recoveryJournal.h"
Packit Service 75d76b
#include "releaseVersions.h"
Packit Service 75d76b
#include "slabDepot.h"
Packit Service 75d76b
#include "slabSummary.h"
Packit Service 75d76b
#include "threadConfig.h"
Packit Service 75d76b
#include "types.h"
Packit Service 75d76b
#include "vdoInternal.h"
Packit Service 75d76b
#include "vdoRecovery.h"
Packit Service 75d76b
#include "volumeGeometry.h"
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Extract the VDO from an AdminCompletion, checking that the current operation
Packit Service 75d76b
 * is a load.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The AdminCompletion's sub-task completion
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return The VDO
Packit Service 75d76b
 **/
Packit Service 75d76b
static inline VDO *vdoFromLoadSubTask(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  return vdoFromAdminSubTask(completion, ADMIN_OPERATION_LOAD);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Finish aborting a load now that any entry to read-only mode is complete.
Packit Service 75d76b
 * This callback is registered in abortLoad().
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void finishAborting(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO *vdo = vdoFromLoadSubTask(completion);
Packit Service 75d76b
  vdo->closeRequired = false;
Packit Service 75d76b
  finishParentCallback(completion);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Make sure the recovery journal is closed when aborting a load.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void closeRecoveryJournalForAbort(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO *vdo = vdoFromLoadSubTask(completion);
Packit Service 75d76b
  prepareAdminSubTask(vdo, finishAborting, finishAborting);
Packit Service 75d76b
  drainRecoveryJournal(vdo->recoveryJournal, ADMIN_STATE_SAVING, completion);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Clean up after an error loading a VDO. This error handler is set in
Packit Service 75d76b
 * loadCallback() and loadVDOComponents().
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void abortLoad(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO *vdo = vdoFromLoadSubTask(completion);
Packit Service 75d76b
  logErrorWithStringError(completion->result, "aborting load");
Packit Service 75d76b
  if (vdo->readOnlyNotifier == NULL) {
Packit Service 75d76b
    // There are no threads, so we're done
Packit Service 75d76b
    finishParentCallback(completion);
Packit Service 75d76b
    return;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  // Preserve the error.
Packit Service 75d76b
  setCompletionResult(completion->parent, completion->result);
Packit Service 75d76b
  if (vdo->recoveryJournal == NULL) {
Packit Service 75d76b
    prepareAdminSubTask(vdo, finishAborting, finishAborting);
Packit Service 75d76b
  } else {
Packit Service 75d76b
    prepareAdminSubTaskOnThread(vdo, closeRecoveryJournalForAbort,
Packit Service 75d76b
                                closeRecoveryJournalForAbort,
Packit Service 75d76b
                                getJournalZoneThread(getThreadConfig(vdo)));
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  waitUntilNotEnteringReadOnlyMode(vdo->readOnlyNotifier, completion);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Wait for the VDO to be in read-only mode.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void waitForReadOnlyMode(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  prepareToFinishParent(completion, completion->parent);
Packit Service 75d76b
  setCompletionResult(completion, VDO_READ_ONLY);
Packit Service 75d76b
  VDO *vdo = vdoFromLoadSubTask(completion);
Packit Service 75d76b
  waitUntilNotEnteringReadOnlyMode(vdo->readOnlyNotifier, completion);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Finish loading the VDO after an error, but leave it in read-only
Packit Service 75d76b
 * mode.  This error handler is set in makeDirty(), scrubSlabs(), and
Packit Service 75d76b
 * loadVDOComponents().
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void continueLoadReadOnly(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO *vdo = vdoFromLoadSubTask(completion);
Packit Service 75d76b
  logErrorWithStringError(completion->result,
Packit Service 75d76b
                          "Entering read-only mode due to load error");
Packit Service 75d76b
  enterReadOnlyMode(vdo->readOnlyNotifier, completion->result);
Packit Service 75d76b
  waitForReadOnlyMode(completion);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Exit recovery mode if necessary now that online slab scrubbing or loading
Packit Service 75d76b
 * is complete. This callback is registrered in scrubSlabs().
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The slab scrubber completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void finishScrubbingSlabs(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO *vdo = completion->parent;
Packit Service 75d76b
  assertOnAdminThread(vdo, __func__);
Packit Service 75d76b
  if (inRecoveryMode(vdo)) {
Packit Service 75d76b
    leaveRecoveryMode(vdo);
Packit Service 75d76b
  } else {
Packit Service 75d76b
    logInfo("VDO commencing normal operation");
Packit Service 75d76b
  }
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Handle an error scrubbing or loading all slabs after the VDO has come
Packit Service 75d76b
 * online. This error handler is registered in scrubSlabs().
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The slab scrubber completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void handleScrubAllError(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO *vdo = completion->parent;
Packit Service 75d76b
  enterReadOnlyMode(vdo->readOnlyNotifier, completion->result);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Initiate slab scrubbing if necessary. This callback is registered in
Packit Service 75d76b
 * prepareToComeOnline().
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion   The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void scrubSlabs(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO *vdo = vdoFromLoadSubTask(completion);
Packit Service 75d76b
  if (!hasUnrecoveredSlabs(vdo->depot)) {
Packit Service 75d76b
    finishParentCallback(completion);
Packit Service 75d76b
    return;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  if (requiresRecovery(vdo)) {
Packit Service 75d76b
    enterRecoveryMode(vdo);
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  prepareAdminSubTask(vdo, finishParentCallback, continueLoadReadOnly);
Packit Service 75d76b
  scrubAllUnrecoveredSlabs(vdo->depot, vdo, finishScrubbingSlabs,
Packit Service 75d76b
                           handleScrubAllError, 0, completion);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * This is the error handler for slab scrubbing. It is registered in
Packit Service 75d76b
 * prepareToComeOnline().
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void handleScrubbingError(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO *vdo = vdoFromLoadSubTask(completion);
Packit Service 75d76b
  enterReadOnlyMode(vdo->readOnlyNotifier, completion->result);
Packit Service 75d76b
  waitForReadOnlyMode(completion);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * This is the callback after the super block is written. It prepares the block
Packit Service 75d76b
 * allocator to come online and start allocating. It is registered in
Packit Service 75d76b
 * makeDirty().
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void prepareToComeOnline(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO               *vdo      = vdoFromLoadSubTask(completion);
Packit Service 75d76b
  SlabDepotLoadType  loadType = NORMAL_LOAD;
Packit Service 75d76b
  if (requiresReadOnlyRebuild(vdo)) {
Packit Service 75d76b
    loadType = REBUILD_LOAD;
Packit Service 75d76b
  } else if (requiresRecovery(vdo)) {
Packit Service 75d76b
    loadType = RECOVERY_LOAD;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  initializeBlockMapFromJournal(vdo->blockMap, vdo->recoveryJournal);
Packit Service 75d76b
Packit Service 75d76b
  prepareAdminSubTask(vdo, scrubSlabs, handleScrubbingError);
Packit Service 75d76b
  prepareToAllocate(vdo->depot, loadType, completion);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Mark the super block as dirty now that everything has been loaded or
Packit Service 75d76b
 * rebuilt.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void makeDirty(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO *vdo = vdoFromLoadSubTask(completion);
Packit Service 75d76b
  if (isReadOnly(vdo->readOnlyNotifier)) {
Packit Service 75d76b
    finishCompletion(completion->parent, VDO_READ_ONLY);
Packit Service 75d76b
    return;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  vdo->state = VDO_DIRTY;
Packit Service 75d76b
  prepareAdminSubTask(vdo, prepareToComeOnline, continueLoadReadOnly);
Packit Service 75d76b
  saveVDOComponentsAsync(vdo, completion);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Callback to do the destructive parts of a load now that the new VDO device
Packit Service 75d76b
 * is being resumed.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void loadCallback(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO *vdo = vdoFromLoadSubTask(completion);
Packit Service 75d76b
  assertOnAdminThread(vdo, __func__);
Packit Service 75d76b
Packit Service 75d76b
  // Prepare the recovery journal for new entries.
Packit Service 75d76b
  openRecoveryJournal(vdo->recoveryJournal, vdo->depot, vdo->blockMap);
Packit Service 75d76b
  vdo->closeRequired = true;
Packit Service 75d76b
  if (isReadOnly(vdo->readOnlyNotifier)) {
Packit Service 75d76b
    // In read-only mode we don't use the allocator and it may not
Packit Service 75d76b
    // even be readable, so use the default structure.
Packit Service 75d76b
    finishCompletion(completion->parent, VDO_READ_ONLY);
Packit Service 75d76b
    return;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  if (requiresReadOnlyRebuild(vdo)) {
Packit Service 75d76b
    prepareAdminSubTask(vdo, makeDirty, abortLoad);
Packit Service 75d76b
    launchRebuild(vdo, completion);
Packit Service 75d76b
    return;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  if (requiresRebuild(vdo)) {
Packit Service 75d76b
    prepareAdminSubTask(vdo, makeDirty, continueLoadReadOnly);
Packit Service 75d76b
    launchRecovery(vdo, completion);
Packit Service 75d76b
    return;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  prepareAdminSubTask(vdo, makeDirty, continueLoadReadOnly);
Packit Service 75d76b
  loadSlabDepot(vdo->depot,
Packit Service 75d76b
                (wasNew(vdo) ? ADMIN_STATE_FORMATTING : ADMIN_STATE_LOADING),
Packit Service 75d76b
                completion, NULL);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
int performVDOLoad(VDO *vdo)
Packit Service 75d76b
{
Packit Service 75d76b
  return performAdminOperation(vdo, ADMIN_OPERATION_LOAD, NULL, loadCallback,
Packit Service 75d76b
                               loadCallback);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
__attribute__((warn_unused_result))
Packit Service 75d76b
static int startVDODecode(VDO *vdo, bool validateConfig)
Packit Service 75d76b
{
Packit Service 75d76b
  int result = validateVDOVersion(vdo);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = decodeVDOComponent(vdo);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  if (!validateConfig) {
Packit Service 75d76b
    return VDO_SUCCESS;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  if (vdo->loadConfig.nonce != vdo->nonce) {
Packit Service 75d76b
    return logErrorWithStringError(VDO_BAD_NONCE, "Geometry nonce %" PRIu64
Packit Service 75d76b
                                   " does not match superblock nonce %llu",
Packit Service 75d76b
                                   vdo->loadConfig.nonce, vdo->nonce);
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  BlockCount blockCount = vdo->layer->getBlockCount(vdo->layer);
Packit Service 75d76b
  return validateVDOConfig(&vdo->config, blockCount, true);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
__attribute__((warn_unused_result))
Packit Service 75d76b
static int finishVDODecode(VDO *vdo)
Packit Service 75d76b
{
Packit Service 75d76b
  Buffer             *buffer       = getComponentBuffer(vdo->superBlock);
Packit Service 75d76b
  const ThreadConfig *threadConfig = getThreadConfig(vdo);
Packit Service 75d76b
  int result = makeRecoveryJournal(vdo->nonce, vdo->layer,
Packit Service 75d76b
                                   getVDOPartition(vdo->layout,
Packit Service 75d76b
                                                   RECOVERY_JOURNAL_PARTITION),
Packit Service 75d76b
                                   vdo->completeRecoveries,
Packit Service 75d76b
                                   vdo->config.recoveryJournalSize,
Packit Service 75d76b
                                   RECOVERY_JOURNAL_TAIL_BUFFER_SIZE,
Packit Service 75d76b
                                   vdo->readOnlyNotifier, threadConfig,
Packit Service 75d76b
                                   &vdo->recoveryJournal);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = decodeRecoveryJournal(vdo->recoveryJournal, buffer);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = decodeSlabDepot(buffer, threadConfig, vdo->nonce, vdo->layer,
Packit Service 75d76b
                           getVDOPartition(vdo->layout,
Packit Service 75d76b
                                           SLAB_SUMMARY_PARTITION),
Packit Service 75d76b
                           vdo->readOnlyNotifier, vdo->recoveryJournal,
Packit Service 75d76b
                           &vdo->depot);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = decodeBlockMap(buffer, vdo->config.logicalBlocks, threadConfig,
Packit Service 75d76b
                          &vdo->blockMap);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  ASSERT_LOG_ONLY((contentLength(buffer) == 0),
Packit Service 75d76b
                  "All decoded component data was used");
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Decode the component data portion of a super block and fill in the
Packit Service 75d76b
 * corresponding portions of the VDO being loaded. This will also allocate the
Packit Service 75d76b
 * recovery journal and slab depot. If this method is called with an
Packit Service 75d76b
 * asynchronous layer (i.e. a thread config which specifies at least one base
Packit Service 75d76b
 * thread), the block map and packer will be constructed as well.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param vdo             The VDO being loaded
Packit Service 75d76b
 * @param validateConfig  Whether to validate the config
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return VDO_SUCCESS or an error
Packit Service 75d76b
 **/
Packit Service 75d76b
__attribute__((warn_unused_result))
Packit Service 75d76b
static int decodeVDO(VDO *vdo, bool validateConfig)
Packit Service 75d76b
{
Packit Service 75d76b
  int result = startVDODecode(vdo, validateConfig);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  const ThreadConfig *threadConfig = getThreadConfig(vdo);
Packit Service 75d76b
  result = makeReadOnlyNotifier(inReadOnlyMode(vdo), threadConfig, vdo->layer,
Packit Service 75d76b
                                &vdo->readOnlyNotifier);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = enableReadOnlyEntry(vdo);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = decodeVDOLayout(getComponentBuffer(vdo->superBlock), &vdo->layout);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = finishVDODecode(vdo);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = makeFlusher(vdo);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  BlockCount maximumAge = getConfiguredBlockMapMaximumAge(vdo);
Packit Service 75d76b
  BlockCount journalLength
Packit Service 75d76b
    = getRecoveryJournalLength(vdo->config.recoveryJournalSize);
Packit Service 75d76b
  if ((maximumAge > (journalLength / 2)) || (maximumAge < 1)) {
Packit Service 75d76b
    return VDO_BAD_CONFIGURATION;
Packit Service 75d76b
  }
Packit Service 75d76b
  result = makeBlockMapCaches(vdo->blockMap, vdo->layer,
Packit Service 75d76b
                              vdo->readOnlyNotifier, vdo->recoveryJournal,
Packit Service 75d76b
                              vdo->nonce, getConfiguredCacheSize(vdo),
Packit Service 75d76b
                              maximumAge);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = ALLOCATE(threadConfig->hashZoneCount, HashZone *, __func__,
Packit Service 75d76b
                    &vdo->hashZones);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  for (ZoneCount zone = 0; zone < threadConfig->hashZoneCount; zone++) {
Packit Service 75d76b
    result = makeHashZone(vdo, zone, &vdo->hashZones[zone]);
Packit Service 75d76b
    if (result != VDO_SUCCESS) {
Packit Service 75d76b
      return result;
Packit Service 75d76b
    }
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = makeLogicalZones(vdo, &vdo->logicalZones);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = ALLOCATE(threadConfig->physicalZoneCount, PhysicalZone *, __func__,
Packit Service 75d76b
                    &vdo->physicalZones);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  for (ZoneCount zone = 0; zone < threadConfig->physicalZoneCount; zone++) {
Packit Service 75d76b
    result = makePhysicalZone(vdo, zone, &vdo->physicalZones[zone]);
Packit Service 75d76b
    if (result != VDO_SUCCESS) {
Packit Service 75d76b
      return result;
Packit Service 75d76b
    }
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  return makePacker(vdo->layer, DEFAULT_PACKER_INPUT_BINS,
Packit Service 75d76b
                    DEFAULT_PACKER_OUTPUT_BINS, threadConfig, &vdo->packer);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Load the components of a VDO. This is the super block load callback
Packit Service 75d76b
 * set by loadCallback().
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void loadVDOComponents(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO *vdo = vdoFromLoadSubTask(completion);
Packit Service 75d76b
Packit Service 75d76b
  prepareCompletion(completion, finishParentCallback, abortLoad,
Packit Service 75d76b
                    completion->callbackThreadID, completion->parent);
Packit Service 75d76b
  finishCompletion(completion, decodeVDO(vdo, true));
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Callback to initiate a pre-load, registered in prepareToLoadVDO().
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param completion  The sub-task completion
Packit Service 75d76b
 **/
Packit Service 75d76b
static void preLoadCallback(VDOCompletion *completion)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO *vdo = vdoFromLoadSubTask(completion);
Packit Service 75d76b
  assertOnAdminThread(vdo, __func__);
Packit Service 75d76b
  prepareAdminSubTask(vdo, loadVDOComponents, abortLoad);
Packit Service 75d76b
  loadSuperBlockAsync(completion, getFirstBlockOffset(vdo), &vdo->superBlock);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
int prepareToLoadVDO(VDO *vdo, const VDOLoadConfig *loadConfig)
Packit Service 75d76b
{
Packit Service 75d76b
  vdo->loadConfig = *loadConfig;
Packit Service 75d76b
  return performAdminOperation(vdo, ADMIN_OPERATION_LOAD, NULL,
Packit Service 75d76b
                               preLoadCallback, preLoadCallback);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
__attribute__((warn_unused_result))
Packit Service 75d76b
static int decodeSynchronousVDO(VDO *vdo, bool validateConfig)
Packit Service 75d76b
{
Packit Service 75d76b
  int result = startVDODecode(vdo, validateConfig);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = decodeVDOLayout(getComponentBuffer(vdo->superBlock), &vdo->layout);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  return finishVDODecode(vdo);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
int loadVDOSuperblock(PhysicalLayer   *layer,
Packit Service 75d76b
                      VolumeGeometry  *geometry,
Packit Service 75d76b
                      bool             validateConfig,
Packit Service 75d76b
                      VDODecoder      *decoder,
Packit Service 75d76b
                      VDO            **vdoPtr)
Packit Service 75d76b
{
Packit Service 75d76b
  VDO *vdo;
Packit Service 75d76b
  int result = makeVDO(layer, &vdo;;
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  setLoadConfigFromGeometry(geometry, &vdo->loadConfig);
Packit Service 75d76b
  result = loadSuperBlock(layer, getFirstBlockOffset(vdo), &vdo->superBlock);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    freeVDO(&vdo;;
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = ((decoder == NULL)
Packit Service 75d76b
            ? decodeSynchronousVDO(vdo, validateConfig)
Packit Service 75d76b
            : decoder(vdo, validateConfig));
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    freeVDO(&vdo;;
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  *vdoPtr = vdo;
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
Packit Service 75d76b
}
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
int loadVDO(PhysicalLayer  *layer,
Packit Service 75d76b
            bool            validateConfig,
Packit Service 75d76b
            VDODecoder     *decoder,
Packit Service 75d76b
            VDO           **vdoPtr)
Packit Service 75d76b
{
Packit Service 75d76b
  VolumeGeometry geometry;
Packit Service 75d76b
  int result = loadVolumeGeometry(layer, &geometry);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  return loadVDOSuperblock(layer, &geometry, validateConfig, decoder, vdoPtr);
Packit Service 75d76b
}