Blame vdo/base/vdo.c

Packit Service 310c69
/*
Packit Service 310c69
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service 310c69
 *
Packit Service 310c69
 * This program is free software; you can redistribute it and/or
Packit Service 310c69
 * modify it under the terms of the GNU General Public License
Packit Service 310c69
 * as published by the Free Software Foundation; either version 2
Packit Service 310c69
 * of the License, or (at your option) any later version.
Packit Service 310c69
 * 
Packit Service 310c69
 * This program is distributed in the hope that it will be useful,
Packit Service 310c69
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 310c69
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 310c69
 * GNU General Public License for more details.
Packit Service 310c69
 * 
Packit Service 310c69
 * You should have received a copy of the GNU General Public License
Packit Service 310c69
 * along with this program; if not, write to the Free Software
Packit Service 310c69
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 310c69
 * 02110-1301, USA. 
Packit Service 310c69
 *
Packit Service 310c69
 * $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/vdo.c#21 $
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
/*
Packit Service 310c69
 * This file contains the main entry points for normal operations on a VDO as
Packit Service 310c69
 * well as functions for constructing and destroying VDO instances (in memory).
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
#include "vdoInternal.h"
Packit Service 310c69
Packit Service 310c69
#include "buffer.h"
Packit Service 310c69
#include "logger.h"
Packit Service 310c69
#include "memoryAlloc.h"
Packit Service 310c69
Packit Service 310c69
#include "adminCompletion.h"
Packit Service 310c69
#include "blockMap.h"
Packit Service 310c69
#include "extent.h"
Packit Service 310c69
#include "hashZone.h"
Packit Service 310c69
#include "header.h"
Packit Service 310c69
#include "logicalZone.h"
Packit Service 310c69
#include "numUtils.h"
Packit Service 310c69
#include "packer.h"
Packit Service 310c69
#include "physicalZone.h"
Packit Service 310c69
#include "readOnlyNotifier.h"
Packit Service 310c69
#include "recoveryJournal.h"
Packit Service 310c69
#include "releaseVersions.h"
Packit Service 310c69
#include "slabDepot.h"
Packit Service 310c69
#include "slabSummary.h"
Packit Service 310c69
#include "statistics.h"
Packit Service 310c69
#include "statusCodes.h"
Packit Service 310c69
#include "threadConfig.h"
Packit Service 310c69
#include "vdoLayout.h"
Packit Service 310c69
#include "vioWrite.h"
Packit Service 310c69
#include "volumeGeometry.h"
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * The master version of the on-disk format of a VDO. This should be
Packit Service 310c69
 * incremented any time the on-disk representation of any VDO structure
Packit Service 310c69
 * changes. Changes which require only online upgrade steps should increment
Packit Service 310c69
 * the minor version. Changes which require an offline upgrade or which can not
Packit Service 310c69
 * be upgraded to at all should increment the major version and set the minor
Packit Service 310c69
 * version to 0.
Packit Service 310c69
 **/
Packit Service 310c69
static const VersionNumber VDO_MASTER_VERSION_67_0 = {
Packit Service 310c69
  .majorVersion = 67,
Packit Service 310c69
  .minorVersion =  0,
Packit Service 310c69
};
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * The current version for the data encoded in the super block. This must
Packit Service 310c69
 * be changed any time there is a change to encoding of the component data
Packit Service 310c69
 * of any VDO component.
Packit Service 310c69
 **/
Packit Service 310c69
static const VersionNumber VDO_COMPONENT_DATA_41_0 = {
Packit Service 310c69
  .majorVersion = 41,
Packit Service 310c69
  .minorVersion =  0,
Packit Service 310c69
};
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * This is the structure that captures the VDO fields saved as a SuperBlock
Packit Service 310c69
 * component.
Packit Service 310c69
 **/
Packit Service 310c69
typedef struct {
Packit Service 310c69
  VDOState  state;
Packit Service 310c69
  uint64_t  completeRecoveries;
Packit Service 310c69
  uint64_t  readOnlyRecoveries;
Packit Service 310c69
  VDOConfig config;
Packit Service 310c69
  Nonce     nonce;
Packit Service 310c69
} __attribute__((packed)) VDOComponent41_0;
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
int allocateVDO(PhysicalLayer *layer, VDO **vdoPtr)
Packit Service 310c69
{
Packit Service 310c69
  int result = registerStatusCodes();
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  VDO *vdo;
Packit Service 310c69
  result = ALLOCATE(1, VDO, __func__, &vdo;;
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  vdo->layer = layer;
Packit Service 310c69
  if (layer->createEnqueueable != NULL) {
Packit Service 310c69
    result = initializeAdminCompletion(vdo, &vdo->adminCompletion);
Packit Service 310c69
    if (result != VDO_SUCCESS) {
Packit Service 310c69
      freeVDO(&vdo;;
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  *vdoPtr = vdo;
Packit Service 310c69
  return VDO_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
int makeVDO(PhysicalLayer *layer, VDO **vdoPtr)
Packit Service 310c69
{
Packit Service 310c69
  VDO *vdo;
Packit Service 310c69
  int result = allocateVDO(layer, &vdo;;
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = makeZeroThreadConfig(&vdo->loadConfig.threadConfig);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    freeVDO(&vdo;;
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  *vdoPtr = vdo;
Packit Service 310c69
  return VDO_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void destroyVDO(VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  freeFlusher(&vdo->flusher);
Packit Service 310c69
  freePacker(&vdo->packer);
Packit Service 310c69
  freeRecoveryJournal(&vdo->recoveryJournal);
Packit Service 310c69
  freeSlabDepot(&vdo->depot);
Packit Service 310c69
  freeVDOLayout(&vdo->layout);
Packit Service 310c69
  freeSuperBlock(&vdo->superBlock);
Packit Service 310c69
  freeBlockMap(&vdo->blockMap);
Packit Service 310c69
Packit Service 310c69
  const ThreadConfig *threadConfig = getThreadConfig(vdo);
Packit Service 310c69
  if (vdo->hashZones != NULL) {
Packit Service 310c69
    for (ZoneCount zone = 0; zone < threadConfig->hashZoneCount; zone++) {
Packit Service 310c69
      freeHashZone(&vdo->hashZones[zone]);
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
  FREE(vdo->hashZones);
Packit Service 310c69
  vdo->hashZones = NULL;
Packit Service 310c69
Packit Service 310c69
  freeLogicalZones(&vdo->logicalZones);
Packit Service 310c69
Packit Service 310c69
  if (vdo->physicalZones != NULL) {
Packit Service 310c69
    for (ZoneCount zone = 0; zone < threadConfig->physicalZoneCount; zone++) {
Packit Service 310c69
      freePhysicalZone(&vdo->physicalZones[zone]);
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
  FREE(vdo->physicalZones);
Packit Service 310c69
  vdo->physicalZones = NULL;
Packit Service 310c69
Packit Service 310c69
  uninitializeAdminCompletion(&vdo->adminCompletion);
Packit Service 310c69
  freeReadOnlyNotifier(&vdo->readOnlyNotifier);
Packit Service 310c69
  freeThreadConfig(&vdo->loadConfig.threadConfig);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void freeVDO(VDO **vdoPtr)
Packit Service 310c69
{
Packit Service 310c69
  if (*vdoPtr == NULL) {
Packit Service 310c69
    return;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  destroyVDO(*vdoPtr);
Packit Service 310c69
  FREE(*vdoPtr);
Packit Service 310c69
  *vdoPtr = NULL;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
size_t getComponentDataSize(VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return (sizeof(VersionNumber)
Packit Service 310c69
          + sizeof(VersionNumber)
Packit Service 310c69
          + sizeof(VDOComponent41_0)
Packit Service 310c69
          + getVDOLayoutEncodedSize(vdo->layout)
Packit Service 310c69
          + getRecoveryJournalEncodedSize()
Packit Service 310c69
          + getSlabDepotEncodedSize()
Packit Service 310c69
          + getBlockMapEncodedSize());
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Encode the VDO master version.
Packit Service 310c69
 *
Packit Service 310c69
 * @param buffer  The buffer in which to encode the version
Packit Service 310c69
 *
Packit Service 310c69
 * @return VDO_SUCCESS or an error
Packit Service 310c69
 **/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static int encodeMasterVersion(Buffer *buffer)
Packit Service 310c69
{
Packit Service 310c69
  return encodeVersionNumber(VDO_MASTER_VERSION_67_0, buffer);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Encode a VDOConfig structure into a buffer.
Packit Service 310c69
 *
Packit Service 310c69
 * @param config  The config structure to encode
Packit Service 310c69
 * @param buffer  A buffer positioned at the start of the encoding
Packit Service 310c69
 *
Packit Service 310c69
 * @return VDO_SUCCESS or an error
Packit Service 310c69
 **/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static int encodeVDOConfig(const VDOConfig *config, Buffer *buffer)
Packit Service 310c69
{
Packit Service 310c69
  int result = putUInt64LEIntoBuffer(buffer, config->logicalBlocks);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = putUInt64LEIntoBuffer(buffer, config->physicalBlocks);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = putUInt64LEIntoBuffer(buffer, config->slabSize);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = putUInt64LEIntoBuffer(buffer, config->recoveryJournalSize);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  return putUInt64LEIntoBuffer(buffer, config->slabJournalBlocks);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Encode the component data for the VDO itself.
Packit Service 310c69
 *
Packit Service 310c69
 * @param vdo     The vdo to encode
Packit Service 310c69
 * @param buffer  The buffer in which to encode the VDO
Packit Service 310c69
 *
Packit Service 310c69
 * @return VDO_SUCCESS or an error
Packit Service 310c69
 **/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static int encodeVDOComponent(const VDO *vdo, Buffer *buffer)
Packit Service 310c69
{
Packit Service 310c69
  int result = encodeVersionNumber(VDO_COMPONENT_DATA_41_0, buffer);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  size_t initialLength = contentLength(buffer);
Packit Service 310c69
Packit Service 310c69
  result = putUInt32LEIntoBuffer(buffer, vdo->state);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = putUInt64LEIntoBuffer(buffer, vdo->completeRecoveries);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = putUInt64LEIntoBuffer(buffer, vdo->readOnlyRecoveries);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = encodeVDOConfig(&vdo->config, buffer);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = putUInt64LEIntoBuffer(buffer, vdo->nonce);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  size_t encodedSize = contentLength(buffer) - initialLength;
Packit Service 310c69
  return ASSERT(encodedSize == sizeof(VDOComponent41_0),
Packit Service 310c69
                "encoded VDO component size must match structure size");
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
static int encodeVDO(VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  Buffer *buffer = getComponentBuffer(vdo->superBlock);
Packit Service 310c69
  int result = resetBufferEnd(buffer, 0);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = encodeMasterVersion(buffer);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = encodeVDOComponent(vdo, buffer);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = encodeVDOLayout(vdo->layout, buffer);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = encodeRecoveryJournal(vdo->recoveryJournal, buffer);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = encodeSlabDepot(vdo->depot, buffer);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = encodeBlockMap(vdo->blockMap, buffer);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  ASSERT_LOG_ONLY((contentLength(buffer) == getComponentDataSize(vdo)),
Packit Service 310c69
                  "All super block component data was encoded");
Packit Service 310c69
  return VDO_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
int saveVDOComponents(VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  int result = encodeVDO(vdo);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  return saveSuperBlock(vdo->layer, vdo->superBlock, getFirstBlockOffset(vdo));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void saveVDOComponentsAsync(VDO *vdo, VDOCompletion *parent)
Packit Service 310c69
{
Packit Service 310c69
  int result = encodeVDO(vdo);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    finishCompletion(parent, result);
Packit Service 310c69
    return;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  saveSuperBlockAsync(vdo->superBlock, getFirstBlockOffset(vdo), parent);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
int saveReconfiguredVDO(VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  Buffer *buffer         = getComponentBuffer(vdo->superBlock);
Packit Service 310c69
  size_t  componentsSize = contentLength(buffer);
Packit Service 310c69
Packit Service 310c69
  byte *components;
Packit Service 310c69
  int   result = copyBytes(buffer, componentsSize, &components);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = resetBufferEnd(buffer, 0);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    FREE(components);
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = encodeMasterVersion(buffer);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    FREE(components);
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = encodeVDOComponent(vdo, buffer);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    FREE(components);
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = putBytes(buffer, componentsSize, components);
Packit Service 310c69
  FREE(components);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  return saveSuperBlock(vdo->layer, vdo->superBlock, getFirstBlockOffset(vdo));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
int decodeVDOVersion(VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return decodeVersionNumber(getComponentBuffer(vdo->superBlock),
Packit Service 310c69
                             &vdo->loadVersion);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
int validateVDOVersion(VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  int result = decodeVDOVersion(vdo);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  ReleaseVersionNumber loadedReleaseVersion
Packit Service 310c69
    = getLoadedReleaseVersion(vdo->superBlock);
Packit Service 310c69
  if (vdo->loadConfig.releaseVersion != loadedReleaseVersion) {
Packit Service 310c69
    return logErrorWithStringError(VDO_UNSUPPORTED_VERSION,
Packit Service 310c69
                                   "Geometry release version %" PRIu32 " does "
Packit Service 310c69
                                   "not match super block release version %"
Packit Service 310c69
                                   PRIu32,
Packit Service 310c69
                                   vdo->loadConfig.releaseVersion,
Packit Service 310c69
                                   loadedReleaseVersion);
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  return validateVersion(VDO_MASTER_VERSION_67_0, vdo->loadVersion, "master");
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Decode a VDOConfig structure from a buffer.
Packit Service 310c69
 *
Packit Service 310c69
 * @param buffer  A buffer positioned at the start of the encoding
Packit Service 310c69
 * @param config  The config structure to receive the decoded values
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static int decodeVDOConfig(Buffer *buffer, VDOConfig *config)
Packit Service 310c69
{
Packit Service 310c69
  BlockCount logicalBlocks;
Packit Service 310c69
  int result = getUInt64LEFromBuffer(buffer, &logicalBlocks);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  BlockCount physicalBlocks;
Packit Service 310c69
  result = getUInt64LEFromBuffer(buffer, &physicalBlocks);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  BlockCount slabSize;
Packit Service 310c69
  result = getUInt64LEFromBuffer(buffer, &slabSize);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  BlockCount recoveryJournalSize;
Packit Service 310c69
  result = getUInt64LEFromBuffer(buffer, &recoveryJournalSize);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  BlockCount slabJournalBlocks;
Packit Service 310c69
  result = getUInt64LEFromBuffer(buffer, &slabJournalBlocks);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  *config = (VDOConfig) {
Packit Service 310c69
    .logicalBlocks       = logicalBlocks,
Packit Service 310c69
    .physicalBlocks      = physicalBlocks,
Packit Service 310c69
    .slabSize            = slabSize,
Packit Service 310c69
    .recoveryJournalSize = recoveryJournalSize,
Packit Service 310c69
    .slabJournalBlocks   = slabJournalBlocks,
Packit Service 310c69
  };
Packit Service 310c69
  return VDO_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Decode the version 41.0 component state for the VDO itself from a buffer.
Packit Service 310c69
 *
Packit Service 310c69
 * @param buffer  A buffer positioned at the start of the encoding
Packit Service 310c69
 * @param state   The state structure to receive the decoded values
Packit Service 310c69
 *
Packit Service 310c69
 * @return VDO_SUCCESS or an error
Packit Service 310c69
 **/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
  static int decodeVDOComponent_41_0(Buffer *buffer, VDOComponent41_0 *state)
Packit Service 310c69
{
Packit Service 310c69
  size_t initialLength = contentLength(buffer);
Packit Service 310c69
Packit Service 310c69
  VDOState vdoState;
Packit Service 310c69
  int result = getUInt32LEFromBuffer(buffer, &vdoState);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  uint64_t completeRecoveries;
Packit Service 310c69
  result = getUInt64LEFromBuffer(buffer, &completeRecoveries);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  uint64_t readOnlyRecoveries;
Packit Service 310c69
  result = getUInt64LEFromBuffer(buffer, &readOnlyRecoveries);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  VDOConfig config;
Packit Service 310c69
  result = decodeVDOConfig(buffer, &config);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  Nonce nonce;
Packit Service 310c69
  result = getUInt64LEFromBuffer(buffer, &nonce);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  *state = (VDOComponent41_0) {
Packit Service 310c69
    .state              = vdoState,
Packit Service 310c69
    .completeRecoveries = completeRecoveries,
Packit Service 310c69
    .readOnlyRecoveries = readOnlyRecoveries,
Packit Service 310c69
    .config             = config,
Packit Service 310c69
    .nonce              = nonce,
Packit Service 310c69
  };
Packit Service 310c69
Packit Service 310c69
  size_t decodedSize = initialLength - contentLength(buffer);
Packit Service 310c69
  return ASSERT(decodedSize == sizeof(VDOComponent41_0),
Packit Service 310c69
                "decoded VDO component size must match structure size");
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
int decodeVDOComponent(VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  Buffer *buffer = getComponentBuffer(vdo->superBlock);
Packit Service 310c69
Packit Service 310c69
  VersionNumber version;
Packit Service 310c69
  int result = decodeVersionNumber(buffer, &version);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = validateVersion(version, VDO_COMPONENT_DATA_41_0,
Packit Service 310c69
                           "VDO component data");
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  VDOComponent41_0 component;
Packit Service 310c69
  result = decodeVDOComponent_41_0(buffer, &component);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  // Copy the decoded component into the VDO structure.
Packit Service 310c69
  vdo->state              = component.state;
Packit Service 310c69
  vdo->loadState          = component.state;
Packit Service 310c69
  vdo->completeRecoveries = component.completeRecoveries;
Packit Service 310c69
  vdo->readOnlyRecoveries = component.readOnlyRecoveries;
Packit Service 310c69
  vdo->config             = component.config;
Packit Service 310c69
  vdo->nonce              = component.nonce;
Packit Service 310c69
  return VDO_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
int validateVDOConfig(const VDOConfig *config,
Packit Service 310c69
                      BlockCount       blockCount,
Packit Service 310c69
                      bool             requireLogical)
Packit Service 310c69
{
Packit Service 310c69
  int result = ASSERT(config->slabSize > 0, "slab size unspecified");
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = ASSERT(isPowerOfTwo(config->slabSize),
Packit Service 310c69
                  "slab size must be a power of two");
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = ASSERT(config->slabSize <= (1 << MAX_SLAB_BITS),
Packit Service 310c69
                  "slab size must be less than or equal to 2^%d",
Packit Service 310c69
                  MAX_SLAB_BITS);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = ASSERT(config->slabJournalBlocks >= MINIMUM_SLAB_JOURNAL_BLOCKS,
Packit Service 310c69
                  "slab journal size meets minimum size");
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = ASSERT(config->slabJournalBlocks <= config->slabSize,
Packit Service 310c69
                  "slab journal size is within expected bound");
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  SlabConfig slabConfig;
Packit Service 310c69
  result = configureSlab(config->slabSize, config->slabJournalBlocks,
Packit Service 310c69
                         &slabConfig);
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = ASSERT((slabConfig.dataBlocks >= 1),
Packit Service 310c69
                  "slab must be able to hold at least one block");
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = ASSERT(config->physicalBlocks > 0, "physical blocks unspecified");
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = ASSERT(config->physicalBlocks <= MAXIMUM_PHYSICAL_BLOCKS,
Packit Service 310c69
                  "physical block count %llu exceeds maximum %llu",
Packit Service 310c69
                  config->physicalBlocks, MAXIMUM_PHYSICAL_BLOCKS);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return VDO_OUT_OF_RANGE;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  // This can't check equality because FileLayer et al can only known about
Packit Service 310c69
  // the storage size, which may not match the super block size.
Packit Service 310c69
  if (blockCount < config->physicalBlocks) {
Packit Service 310c69
    logError("A physical size of %llu blocks was specified,"
Packit Service 310c69
             " but that is smaller than the %llu blocks"
Packit Service 310c69
             " configured in the VDO super block",
Packit Service 310c69
             blockCount, config->physicalBlocks);
Packit Service 310c69
    return VDO_PARAMETER_MISMATCH;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = ASSERT(!requireLogical || (config->logicalBlocks > 0),
Packit Service 310c69
                  "logical blocks unspecified");
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = ASSERT(config->logicalBlocks <= MAXIMUM_LOGICAL_BLOCKS,
Packit Service 310c69
                  "logical blocks too large");
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = ASSERT(config->recoveryJournalSize > 0,
Packit Service 310c69
                  "recovery journal size unspecified");
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = ASSERT(isPowerOfTwo(config->recoveryJournalSize),
Packit Service 310c69
                  "recovery journal size must be a power of two");
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  return result;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Notify a VDO that it is going read-only. This will save the read-only state
Packit Service 310c69
 * to the super block.
Packit Service 310c69
 *
Packit Service 310c69
 * 

Implements ReadOnlyNotification.

Packit Service 310c69
 *
Packit Service 310c69
 * @param listener  The VDO
Packit Service 310c69
 * @param parent    The completion to notify in order to acknowledge the
Packit Service 310c69
 *                  notification
Packit Service 310c69
 **/
Packit Service 310c69
static void notifyVDOOfReadOnlyMode(void *listener, VDOCompletion *parent)
Packit Service 310c69
{
Packit Service 310c69
  VDO *vdo = listener;
Packit Service 310c69
  if (inReadOnlyMode(vdo)) {
Packit Service 310c69
    completeCompletion(parent);
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  vdo->state = VDO_READ_ONLY_MODE;
Packit Service 310c69
  saveVDOComponentsAsync(vdo, parent);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
int enableReadOnlyEntry(VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return registerReadOnlyListener(vdo->readOnlyNotifier, vdo,
Packit Service 310c69
                                  notifyVDOOfReadOnlyMode,
Packit Service 310c69
                                  getAdminThread(getThreadConfig(vdo)));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool inReadOnlyMode(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return (vdo->state == VDO_READ_ONLY_MODE);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool isClean(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return ((vdo->state == VDO_CLEAN) || (vdo->state == VDO_NEW));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool wasClean(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return ((vdo->loadState == VDO_CLEAN) || (vdo->loadState == VDO_NEW));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool wasNew(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return (vdo->loadState == VDO_NEW);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool requiresReadOnlyRebuild(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return ((vdo->loadState == VDO_FORCE_REBUILD)
Packit Service 310c69
          || (vdo->loadState == VDO_REBUILD_FOR_UPGRADE));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool requiresRebuild(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return ((vdo->state == VDO_DIRTY)
Packit Service 310c69
          || (vdo->state == VDO_FORCE_REBUILD)
Packit Service 310c69
          || (vdo->state == VDO_REPLAYING)
Packit Service 310c69
          || (vdo->state == VDO_REBUILD_FOR_UPGRADE));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool requiresRecovery(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return ((vdo->loadState == VDO_DIRTY) || (vdo->loadState == VDO_REPLAYING)
Packit Service 310c69
          || (vdo->loadState == VDO_RECOVERING));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool isReplaying(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return (vdo->state == VDO_REPLAYING);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool inRecoveryMode(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return (vdo->state == VDO_RECOVERING);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void enterRecoveryMode(VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  assertOnAdminThread(vdo, __func__);
Packit Service 310c69
Packit Service 310c69
  if (inReadOnlyMode(vdo)) {
Packit Service 310c69
    return;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  logInfo("Entering recovery mode");
Packit Service 310c69
  vdo->state = VDO_RECOVERING;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void leaveRecoveryMode(VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  assertOnAdminThread(vdo, __func__);
Packit Service 310c69
Packit Service 310c69
  /*
Packit Service 310c69
   * Since scrubbing can be stopped by vdoClose during recovery mode,
Packit Service 310c69
   * do not change the VDO state if there are outstanding unrecovered slabs.
Packit Service 310c69
   */
Packit Service 310c69
  if (inReadOnlyMode(vdo)) {
Packit Service 310c69
    return;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  ASSERT_LOG_ONLY(inRecoveryMode(vdo), "VDO is in recovery mode");
Packit Service 310c69
  logInfo("Exiting recovery mode");
Packit Service 310c69
  vdo->state = VDO_DIRTY;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void makeVDOReadOnly(VDO *vdo, int errorCode)
Packit Service 310c69
{
Packit Service 310c69
  enterReadOnlyMode(vdo->readOnlyNotifier, errorCode);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool setVDOCompressing(VDO *vdo, bool enableCompression)
Packit Service 310c69
{
Packit Service 310c69
  bool stateChanged = compareAndSwapBool(&vdo->compressing, !enableCompression,
Packit Service 310c69
                                         enableCompression);
Packit Service 310c69
  if (stateChanged && !enableCompression) {
Packit Service 310c69
    // Flushing the packer is asynchronous, but we don't care when it
Packit Service 310c69
    // finishes.
Packit Service 310c69
    flushPacker(vdo->packer);
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  logInfo("compression is %s", (enableCompression ? "enabled" : "disabled"));
Packit Service 310c69
  return (stateChanged ? !enableCompression : enableCompression);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool getVDOCompressing(VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return atomicLoadBool(&vdo->compressing);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
static size_t getBlockMapCacheSize(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return ((size_t) vdo->loadConfig.cacheSize) * VDO_BLOCK_SIZE;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Tally the hash lock statistics from all the hash zones.
Packit Service 310c69
 *
Packit Service 310c69
 * @param vdo  The vdo to query
Packit Service 310c69
 *
Packit Service 310c69
 * @return The sum of the hash lock statistics from all hash zones
Packit Service 310c69
 **/
Packit Service 310c69
static HashLockStatistics getHashLockStatistics(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  HashLockStatistics totals;
Packit Service 310c69
  memset(&totals, 0, sizeof(totals));
Packit Service 310c69
Packit Service 310c69
  const ThreadConfig *threadConfig = getThreadConfig(vdo);
Packit Service 310c69
  for (ZoneCount zone = 0; zone < threadConfig->hashZoneCount; zone++) {
Packit Service 310c69
    HashLockStatistics stats  = getHashZoneStatistics(vdo->hashZones[zone]);
Packit Service 310c69
    totals.dedupeAdviceValid        += stats.dedupeAdviceValid;
Packit Service 310c69
    totals.dedupeAdviceStale        += stats.dedupeAdviceStale;
Packit Service 310c69
    totals.concurrentDataMatches    += stats.concurrentDataMatches;
Packit Service 310c69
    totals.concurrentHashCollisions += stats.concurrentHashCollisions;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  return totals;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Get the current error statistics from VDO.
Packit Service 310c69
 *
Packit Service 310c69
 * @param vdo  The vdo to query
Packit Service 310c69
 *
Packit Service 310c69
 * @return a copy of the current VDO error counters
Packit Service 310c69
 **/
Packit Service 310c69
static ErrorStatistics getVDOErrorStatistics(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  /*
Packit Service 310c69
   * The error counts can be incremented from arbitrary threads and so must be
Packit Service 310c69
   * incremented atomically, but they are just statistics with no semantics
Packit Service 310c69
   * that could rely on memory order, so unfenced reads are sufficient.
Packit Service 310c69
   */
Packit Service 310c69
  const AtomicErrorStatistics *atoms = &vdo->errorStats;
Packit Service 310c69
  return (ErrorStatistics) {
Packit Service 310c69
    .invalidAdvicePBNCount = relaxedLoad64(&atoms->invalidAdvicePBNCount),
Packit Service 310c69
    .noSpaceErrorCount     = relaxedLoad64(&atoms->noSpaceErrorCount),
Packit Service 310c69
    .readOnlyErrorCount    = relaxedLoad64(&atoms->readOnlyErrorCount),
Packit Service 310c69
  };
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
static const char *describeWritePolicy(WritePolicy policy)
Packit Service 310c69
{
Packit Service 310c69
  switch (policy) {
Packit Service 310c69
  case WRITE_POLICY_ASYNC:
Packit Service 310c69
    return "async";
Packit Service 310c69
  case WRITE_POLICY_ASYNC_UNSAFE:
Packit Service 310c69
    return "async-unsafe";
Packit Service 310c69
  case WRITE_POLICY_SYNC:
Packit Service 310c69
    return "sync";
Packit Service 310c69
  default:
Packit Service 310c69
    return "unknown";
Packit Service 310c69
  }
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void getVDOStatistics(const VDO *vdo, VDOStatistics *stats)
Packit Service 310c69
{
Packit Service 310c69
  // These are immutable properties of the VDO object, so it is safe to
Packit Service 310c69
  // query them from any thread.
Packit Service 310c69
  RecoveryJournal *journal  = vdo->recoveryJournal;
Packit Service 310c69
  SlabDepot       *depot    = vdo->depot;
Packit Service 310c69
  // XXX config.physicalBlocks is actually mutated during resize and is in a
Packit Service 310c69
  // packed structure, but resize runs on the admin thread so we're usually OK.
Packit Service 310c69
  stats->version            = STATISTICS_VERSION;
Packit Service 310c69
  stats->releaseVersion     = CURRENT_RELEASE_VERSION_NUMBER;
Packit Service 310c69
  stats->logicalBlocks      = vdo->config.logicalBlocks;
Packit Service 310c69
  stats->physicalBlocks     = vdo->config.physicalBlocks;
Packit Service 310c69
  stats->blockSize          = VDO_BLOCK_SIZE;
Packit Service 310c69
  stats->completeRecoveries = vdo->completeRecoveries;
Packit Service 310c69
  stats->readOnlyRecoveries = vdo->readOnlyRecoveries;
Packit Service 310c69
  stats->blockMapCacheSize  = getBlockMapCacheSize(vdo);
Packit Service 310c69
  snprintf(stats->writePolicy, sizeof(stats->writePolicy), "%s",
Packit Service 310c69
           describeWritePolicy(getWritePolicy(vdo)));
Packit Service 310c69
Packit Service 310c69
  // The callees are responsible for thread-safety.
Packit Service 310c69
  stats->dataBlocksUsed     = getPhysicalBlocksAllocated(vdo);
Packit Service 310c69
  stats->overheadBlocksUsed = getPhysicalBlocksOverhead(vdo);
Packit Service 310c69
  stats->logicalBlocksUsed  = getJournalLogicalBlocksUsed(journal);
Packit Service 310c69
  stats->allocator          = getDepotBlockAllocatorStatistics(depot);
Packit Service 310c69
  stats->journal            = getRecoveryJournalStatistics(journal);
Packit Service 310c69
  stats->packer             = getPackerStatistics(vdo->packer);
Packit Service 310c69
  stats->slabJournal        = getDepotSlabJournalStatistics(depot);
Packit Service 310c69
  stats->slabSummary        = getSlabSummaryStatistics(getSlabSummary(depot));
Packit Service 310c69
  stats->refCounts          = getDepotRefCountsStatistics(depot);
Packit Service 310c69
  stats->blockMap           = getBlockMapStatistics(vdo->blockMap);
Packit Service 310c69
  stats->hashLock           = getHashLockStatistics(vdo);
Packit Service 310c69
  stats->errors             = getVDOErrorStatistics(vdo);
Packit Service 310c69
  SlabCount slabTotal       = getDepotSlabCount(depot);
Packit Service 310c69
  stats->recoveryPercentage
Packit Service 310c69
    = (slabTotal - getDepotUnrecoveredSlabCount(depot)) * 100 / slabTotal;
Packit Service 310c69
Packit Service 310c69
  // The "state" field is mutable, but we just need a unfenced atomic read.
Packit Service 310c69
  VDOState state        = *((const volatile VDOState *) &vdo->state);
Packit Service 310c69
  stats->inRecoveryMode = (state == VDO_RECOVERING);
Packit Service 310c69
  snprintf(stats->mode, sizeof(stats->mode), "%s", describeVDOState(state));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
BlockCount getPhysicalBlocksAllocated(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return (getDepotAllocatedBlocks(vdo->depot)
Packit Service 310c69
          - getJournalBlockMapDataBlocksUsed(vdo->recoveryJournal));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
BlockCount getPhysicalBlocksFree(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return getDepotFreeBlocks(vdo->depot);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
BlockCount getPhysicalBlocksOverhead(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  // XXX config.physicalBlocks is actually mutated during resize and is in a
Packit Service 310c69
  // packed structure, but resize runs on admin thread so we're usually OK.
Packit Service 310c69
  return (vdo->config.physicalBlocks
Packit Service 310c69
          - getDepotDataBlocks(vdo->depot)
Packit Service 310c69
          + getJournalBlockMapDataBlocksUsed(vdo->recoveryJournal));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
BlockCount getTotalBlockMapBlocks(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return (getNumberOfFixedBlockMapPages(vdo->blockMap)
Packit Service 310c69
          + getJournalBlockMapDataBlocksUsed(vdo->recoveryJournal));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
WritePolicy getWritePolicy(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return vdo->loadConfig.writePolicy;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void setWritePolicy(VDO *vdo, WritePolicy new)
Packit Service 310c69
{
Packit Service 310c69
  vdo->loadConfig.writePolicy = new;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
const VDOLoadConfig *getVDOLoadConfig(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return &vdo->loadConfig;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
const ThreadConfig *getThreadConfig(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return vdo->loadConfig.threadConfig;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
BlockCount getConfiguredBlockMapMaximumAge(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return vdo->loadConfig.maximumAge;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
PageCount getConfiguredCacheSize(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return vdo->loadConfig.cacheSize;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
PhysicalBlockNumber getFirstBlockOffset(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return vdo->loadConfig.firstBlockOffset;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
BlockMap *getBlockMap(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return vdo->blockMap;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
SlabDepot *getSlabDepot(VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return vdo->depot;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
RecoveryJournal *getRecoveryJournal(VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return vdo->recoveryJournal;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void dumpVDOStatus(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  dumpFlusher(vdo->flusher);
Packit Service 310c69
  dumpRecoveryJournalStatistics(vdo->recoveryJournal);
Packit Service 310c69
  dumpPacker(vdo->packer);
Packit Service 310c69
  dumpSlabDepot(vdo->depot);
Packit Service 310c69
Packit Service 310c69
  const ThreadConfig *threadConfig = getThreadConfig(vdo);
Packit Service 310c69
  for (ZoneCount zone = 0; zone < threadConfig->logicalZoneCount; zone++) {
Packit Service 310c69
    dumpLogicalZone(getLogicalZone(vdo->logicalZones, zone));
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  for (ZoneCount zone = 0; zone < threadConfig->physicalZoneCount; zone++) {
Packit Service 310c69
    dumpPhysicalZone(vdo->physicalZones[zone]);
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  for (ZoneCount zone = 0; zone < threadConfig->hashZoneCount; zone++) {
Packit Service 310c69
    dumpHashZone(vdo->hashZones[zone]);
Packit Service 310c69
  }
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void setVDOTracingFlags(VDO *vdo, bool vioTracing)
Packit Service 310c69
{
Packit Service 310c69
  vdo->vioTraceRecording = vioTracing;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool vdoVIOTracingEnabled(const VDO *vdo)
Packit Service 310c69
{
Packit Service 310c69
  return ((vdo != NULL) && vdo->vioTraceRecording);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void assertOnAdminThread(VDO *vdo, const char *name)
Packit Service 310c69
{
Packit Service 310c69
  ASSERT_LOG_ONLY((getCallbackThreadID()
Packit Service 310c69
                   == getAdminThread(getThreadConfig(vdo))),
Packit Service 310c69
                  "%s called on admin thread", name);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void assertOnLogicalZoneThread(const VDO  *vdo,
Packit Service 310c69
                               ZoneCount   logicalZone,
Packit Service 310c69
                               const char *name)
Packit Service 310c69
{
Packit Service 310c69
  ASSERT_LOG_ONLY((getCallbackThreadID()
Packit Service 310c69
                   == getLogicalZoneThread(getThreadConfig(vdo), logicalZone)),
Packit Service 310c69
                  "%s called on logical thread", name);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void assertOnPhysicalZoneThread(const VDO  *vdo,
Packit Service 310c69
                                ZoneCount   physicalZone,
Packit Service 310c69
                                const char *name)
Packit Service 310c69
{
Packit Service 310c69
  ASSERT_LOG_ONLY((getCallbackThreadID()
Packit Service 310c69
                   == getPhysicalZoneThread(getThreadConfig(vdo),
Packit Service 310c69
                                            physicalZone)),
Packit Service 310c69
                  "%s called on physical thread", name);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
HashZone *selectHashZone(const VDO *vdo, const UdsChunkName *name)
Packit Service 310c69
{
Packit Service 310c69
  /*
Packit Service 310c69
   * Use a fragment of the chunk name as a hash code. To ensure uniform
Packit Service 310c69
   * distributions, it must not overlap with fragments used elsewhere. Eight
Packit Service 310c69
   * bits of hash should suffice since the number of hash zones is small.
Packit Service 310c69
   */
Packit Service 310c69
  // XXX Make a central repository for these offsets ala hashUtils.
Packit Service 310c69
  // XXX Verify that the first byte is independent enough.
Packit Service 310c69
  uint32_t hash = name->name[0];
Packit Service 310c69
Packit Service 310c69
  /*
Packit Service 310c69
   * Scale the 8-bit hash fragment to a zone index by treating it as a binary
Packit Service 310c69
   * fraction and multiplying that by the zone count. If the hash is uniformly
Packit Service 310c69
   * distributed over [0 .. 2^8-1], then (hash * count / 2^8) should be
Packit Service 310c69
   * uniformly distributed over [0 .. count-1]. The multiply and shift is much
Packit Service 310c69
   * faster than a divide (modulus) on X86 CPUs.
Packit Service 310c69
   */
Packit Service 310c69
  return vdo->hashZones[(hash * getThreadConfig(vdo)->hashZoneCount) >> 8];
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
int getPhysicalZone(const VDO            *vdo,
Packit Service 310c69
                    PhysicalBlockNumber   pbn,
Packit Service 310c69
                    PhysicalZone        **zonePtr)
Packit Service 310c69
{
Packit Service 310c69
  if (pbn == ZERO_BLOCK) {
Packit Service 310c69
    *zonePtr = NULL;
Packit Service 310c69
    return VDO_SUCCESS;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  // Used because it does a more restrictive bounds check than getSlab(), and
Packit Service 310c69
  // done first because it won't trigger read-only mode on an invalid PBN.
Packit Service 310c69
  if (!isPhysicalDataBlock(vdo->depot, pbn)) {
Packit Service 310c69
    return VDO_OUT_OF_RANGE;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  // With the PBN already checked, we should always succeed in finding a slab.
Packit Service 310c69
  Slab *slab = getSlab(vdo->depot, pbn);
Packit Service 310c69
  int result = ASSERT(slab != NULL, "getSlab must succeed on all valid PBNs");
Packit Service 310c69
  if (result != VDO_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  *zonePtr = vdo->physicalZones[getSlabZoneNumber(slab)];
Packit Service 310c69
  return VDO_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
ZonedPBN validateDedupeAdvice(VDO                *vdo,
Packit Service 310c69
                              const DataLocation *advice,
Packit Service 310c69
                              LogicalBlockNumber  lbn)
Packit Service 310c69
{
Packit Service 310c69
  ZonedPBN noAdvice = { .pbn = ZERO_BLOCK };
Packit Service 310c69
  if (advice == NULL) {
Packit Service 310c69
    return noAdvice;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  // Don't use advice that's clearly meaningless.
Packit Service 310c69
  if ((advice->state == MAPPING_STATE_UNMAPPED)
Packit Service 310c69
      || (advice->pbn == ZERO_BLOCK)) {
Packit Service 310c69
    logDebug("Invalid advice from deduplication server: pbn %llu, "
Packit Service 310c69
             "state %u. Giving up on deduplication of logical block %llu",
Packit Service 310c69
             advice->pbn, advice->state, lbn);
Packit Service 310c69
    atomicAdd64(&vdo->errorStats.invalidAdvicePBNCount, 1);
Packit Service 310c69
    return noAdvice;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  PhysicalZone  *zone;
Packit Service 310c69
  int result = getPhysicalZone(vdo, advice->pbn, &zone);
Packit Service 310c69
  if ((result != VDO_SUCCESS) || (zone == NULL)) {
Packit Service 310c69
    logDebug("Invalid physical block number from deduplication server: %"
Packit Service 310c69
             PRIu64 ", giving up on deduplication of logical block %llu",
Packit Service 310c69
             advice->pbn, lbn);
Packit Service 310c69
    atomicAdd64(&vdo->errorStats.invalidAdvicePBNCount, 1);
Packit Service 310c69
    return noAdvice;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  return (ZonedPBN) {
Packit Service 310c69
    .pbn   = advice->pbn,
Packit Service 310c69
    .state = advice->state,
Packit Service 310c69
    .zone  = zone,
Packit Service 310c69
  };
Packit Service 310c69
}