Blame source/vdo/base/volumeGeometry.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/volumeGeometry.c#10 $
Packit Service 75d76b
 */
Packit Service 75d76b
Packit Service 75d76b
#include "volumeGeometry.h"
Packit Service 75d76b
Packit Service 75d76b
#include "buffer.h"
Packit Service 75d76b
#include "logger.h"
Packit Service 75d76b
#include "memoryAlloc.h"
Packit Service 75d76b
#include "numeric.h"
Packit Service 75d76b
#include "permassert.h"
Packit Service 75d76b
Packit Service 75d76b
#include "constants.h"
Packit Service 75d76b
#include "header.h"
Packit Service 75d76b
#include "physicalLayer.h"
Packit Service 75d76b
#include "releaseVersions.h"
Packit Service 75d76b
#include "statusCodes.h"
Packit Service 75d76b
#include "types.h"
Packit Service 75d76b
Packit Service 75d76b
enum {
Packit Service 75d76b
  GEOMETRY_BLOCK_LOCATION = 0,
Packit Service 75d76b
  MAGIC_NUMBER_SIZE       = 8,
Packit Service 75d76b
};
Packit Service 75d76b
Packit Service 75d76b
typedef struct {
Packit Service 75d76b
  char            magicNumber[MAGIC_NUMBER_SIZE];
Packit Service 75d76b
  Header          header;
Packit Service 75d76b
  VolumeGeometry  geometry;
Packit Service 75d76b
  CRC32Checksum   checksum;
Packit Service 75d76b
} __attribute__((packed)) GeometryBlock;
Packit Service 75d76b
Packit Service 75d76b
static const Header GEOMETRY_BLOCK_HEADER_4_0 = {
Packit Service 75d76b
  .id = GEOMETRY_BLOCK,
Packit Service 75d76b
  .version = {
Packit Service 75d76b
    .majorVersion = 4,
Packit Service 75d76b
    .minorVersion = 0,
Packit Service 75d76b
  },
Packit Service 75d76b
  // Note: this size isn't just the payload size following the header, like it
Packit Service 75d76b
  // is everywhere else in VDO.
Packit Service 75d76b
  .size = sizeof(GeometryBlock),
Packit Service 75d76b
};
Packit Service 75d76b
Packit Service 75d76b
static const byte MAGIC_NUMBER[MAGIC_NUMBER_SIZE + 1] = "dmvdo001";
Packit Service 75d76b
Packit Service 75d76b
static const ReleaseVersionNumber COMPATIBLE_RELEASE_VERSIONS[] = {
Packit Service 75d76b
  MAGNESIUM_RELEASE_VERSION_NUMBER,
Packit Service 75d76b
};
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Determine whether the supplied release version can be understood by
Packit Service 75d76b
 * the VDO code.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param version  The release version number to check
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return True if the given version can be loaded.
Packit Service 75d76b
 **/
Packit Service 75d76b
static inline bool isLoadableReleaseVersion(ReleaseVersionNumber version)
Packit Service 75d76b
{
Packit Service 75d76b
  if (version == CURRENT_RELEASE_VERSION_NUMBER) {
Packit Service 75d76b
    return true;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  for (unsigned int i = 0; i < COUNT_OF(COMPATIBLE_RELEASE_VERSIONS); i++) {
Packit Service 75d76b
    if (version == COMPATIBLE_RELEASE_VERSIONS[i]) {
Packit Service 75d76b
      return true;
Packit Service 75d76b
    }
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  return false;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Decode the on-disk representation of an index configuration from a buffer.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param buffer  A buffer positioned at the start of the encoding
Packit Service 75d76b
 * @param config  The structure to receive the decoded fields
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return UDS_SUCCESS or an error
Packit Service 75d76b
 **/
Packit Service 75d76b
static int decodeIndexConfig(Buffer *buffer, IndexConfig *config)
Packit Service 75d76b
{
Packit Service 75d76b
  uint32_t mem;
Packit Service 75d76b
  int result = getUInt32LEFromBuffer(buffer, &mem;;
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  uint32_t checkpointFrequency;
Packit Service 75d76b
  result = getUInt32LEFromBuffer(buffer, &checkpointFrequency);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  bool sparse;
Packit Service 75d76b
  result = getBoolean(buffer, &sparse);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  *config = (IndexConfig) {
Packit Service 75d76b
    .mem                 = mem,
Packit Service 75d76b
    .checkpointFrequency = checkpointFrequency,
Packit Service 75d76b
    .sparse              = sparse,
Packit Service 75d76b
  };
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Encode the on-disk representation of an index configuration into a buffer.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param config  The index configuration to encode
Packit Service 75d76b
 * @param buffer  A buffer positioned at the start of the encoding
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return UDS_SUCCESS or an error
Packit Service 75d76b
 **/
Packit Service 75d76b
static int encodeIndexConfig(const IndexConfig *config, Buffer *buffer)
Packit Service 75d76b
{
Packit Service 75d76b
  int result = putUInt32LEIntoBuffer(buffer, config->mem);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = putUInt32LEIntoBuffer(buffer, config->checkpointFrequency);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  return putBoolean(buffer, config->sparse);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Decode the on-disk representation of a volume region from a buffer.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param buffer  A buffer positioned at the start of the encoding
Packit Service 75d76b
 * @param region  The structure to receive the decoded fields
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return UDS_SUCCESS or an error
Packit Service 75d76b
 **/
Packit Service 75d76b
static int decodeVolumeRegion(Buffer *buffer, VolumeRegion *region)
Packit Service 75d76b
{
Packit Service 75d76b
  VolumeRegionID id;
Packit Service 75d76b
  int result = getUInt32LEFromBuffer(buffer, &id;;
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  PhysicalBlockNumber startBlock;
Packit Service 75d76b
  result = getUInt64LEFromBuffer(buffer, &startBlock);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  *region = (VolumeRegion) {
Packit Service 75d76b
    .id         = id,
Packit Service 75d76b
    .startBlock = startBlock,
Packit Service 75d76b
  };
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Encode the on-disk representation of a volume region into a buffer.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param region  The region to encode
Packit Service 75d76b
 * @param buffer  A buffer positioned at the start of the encoding
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return UDS_SUCCESS or an error
Packit Service 75d76b
 **/
Packit Service 75d76b
static int encodeVolumeRegion(const VolumeRegion *region, Buffer *buffer)
Packit Service 75d76b
{
Packit Service 75d76b
  int result = putUInt32LEIntoBuffer(buffer, region->id);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  return putUInt64LEIntoBuffer(buffer, region->startBlock);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Decode the on-disk representation of a volume geometry from a buffer.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param buffer    A buffer positioned at the start of the encoding
Packit Service 75d76b
 * @param geometry  The structure to receive the decoded fields
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return UDS_SUCCESS or an error
Packit Service 75d76b
 **/
Packit Service 75d76b
static int decodeVolumeGeometry(Buffer *buffer, VolumeGeometry *geometry)
Packit Service 75d76b
{
Packit Service 75d76b
  ReleaseVersionNumber releaseVersion;
Packit Service 75d76b
  int result = getUInt32LEFromBuffer(buffer, &releaseVersion);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  Nonce nonce;
Packit Service 75d76b
  result = getUInt64LEFromBuffer(buffer, &nonce);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  geometry->releaseVersion = releaseVersion;
Packit Service 75d76b
  geometry->nonce          = nonce;
Packit Service 75d76b
Packit Service 75d76b
  result = getBytesFromBuffer(buffer, sizeof(UUID), geometry->uuid);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  for (VolumeRegionID id = 0; id < VOLUME_REGION_COUNT; id++) {
Packit Service 75d76b
    result = decodeVolumeRegion(buffer, &geometry->regions[id]);
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 decodeIndexConfig(buffer, &geometry->indexConfig);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Encode the on-disk representation of a volume geometry into a buffer.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param geometry  The geometry to encode
Packit Service 75d76b
 * @param buffer    A buffer positioned at the start of the encoding
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return UDS_SUCCESS or an error
Packit Service 75d76b
 **/
Packit Service 75d76b
static int encodeVolumeGeometry(const VolumeGeometry *geometry, Buffer *buffer)
Packit Service 75d76b
{
Packit Service 75d76b
  int result = putUInt32LEIntoBuffer(buffer, geometry->releaseVersion);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = putUInt64LEIntoBuffer(buffer, geometry->nonce);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = putBytes(buffer, sizeof(UUID), geometry->uuid);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  for (VolumeRegionID id = 0; id < VOLUME_REGION_COUNT; id++) {
Packit Service 75d76b
    result = encodeVolumeRegion(&geometry->regions[id], buffer);
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 encodeIndexConfig(&geometry->indexConfig, buffer);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Decode the on-disk representation of a geometry block, up to but not
Packit Service 75d76b
 * including the checksum, from a buffer.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param buffer    A buffer positioned at the start of the block
Packit Service 75d76b
 * @param geometry  The structure to receive the decoded volume geometry fields
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return UDS_SUCCESS or an error
Packit Service 75d76b
 **/
Packit Service 75d76b
static int decodeGeometryBlock(Buffer *buffer, VolumeGeometry *geometry)
Packit Service 75d76b
{
Packit Service 75d76b
  if (!hasSameBytes(buffer, MAGIC_NUMBER, MAGIC_NUMBER_SIZE)) {
Packit Service 75d76b
    return VDO_BAD_MAGIC;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  int result = skipForward(buffer, MAGIC_NUMBER_SIZE);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  Header header;
Packit Service 75d76b
  result = decodeHeader(buffer, &header);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = validateHeader(&GEOMETRY_BLOCK_HEADER_4_0, &header, true, __func__);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = decodeVolumeGeometry(buffer, geometry);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  // Leave the CRC for the caller to decode and verify.
Packit Service 75d76b
  return ASSERT(header.size
Packit Service 75d76b
                == (uncompactedAmount(buffer) + sizeof(CRC32Checksum)),
Packit Service 75d76b
                "should have decoded up to the geometry checksum");
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Encode the on-disk representation of a geometry block, up to but not
Packit Service 75d76b
 * including the checksum, into a buffer.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param geometry  The volume geometry to encode into the block
Packit Service 75d76b
 * @param buffer    A buffer positioned at the start of the block
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return UDS_SUCCESS or an error
Packit Service 75d76b
 **/
Packit Service 75d76b
static int encodeGeometryBlock(const VolumeGeometry *geometry, Buffer *buffer)
Packit Service 75d76b
{
Packit Service 75d76b
  int result = putBytes(buffer, MAGIC_NUMBER_SIZE, MAGIC_NUMBER);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = encodeHeader(&GEOMETRY_BLOCK_HEADER_4_0, buffer);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = encodeVolumeGeometry(geometry, buffer);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  // Leave the CRC for the caller to compute and encode.
Packit Service 75d76b
  return ASSERT(GEOMETRY_BLOCK_HEADER_4_0.size
Packit Service 75d76b
                == (contentLength(buffer) + sizeof(CRC32Checksum)),
Packit Service 75d76b
                "should have decoded up to the geometry checksum");
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**
Packit Service 75d76b
 * Allocate a block-size buffer to read the geometry from the physical layer,
Packit Service 75d76b
 * read the block, and return the buffer.
Packit Service 75d76b
 *
Packit Service 75d76b
 * @param [in]  layer     The physical layer containing the block to read
Packit Service 75d76b
 * @param [out] blockPtr  A pointer to receive the allocated buffer
Packit Service 75d76b
 *
Packit Service 75d76b
 * @return VDO_SUCCESS or an error code
Packit Service 75d76b
 **/
Packit Service 75d76b
static int readGeometryBlock(PhysicalLayer *layer, byte **blockPtr)
Packit Service 75d76b
{
Packit Service 75d76b
  int result = ASSERT(layer->reader != NULL, "Layer must have a sync reader");
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  char *block;
Packit Service 75d76b
  result = layer->allocateIOBuffer(layer, VDO_BLOCK_SIZE, "geometry block",
Packit Service 75d76b
                                   &block);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = layer->reader(layer, GEOMETRY_BLOCK_LOCATION, 1, block, NULL);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    FREE(block);
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  *blockPtr = (byte *) block;
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
int loadVolumeGeometry(PhysicalLayer *layer, VolumeGeometry *geometry)
Packit Service 75d76b
{
Packit Service 75d76b
  byte *block;
Packit Service 75d76b
  int result = readGeometryBlock(layer, &block);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  Buffer *buffer;
Packit Service 75d76b
  result = wrapBuffer(block, VDO_BLOCK_SIZE, VDO_BLOCK_SIZE, &buffer);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    FREE(block);
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = decodeGeometryBlock(buffer, geometry);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    freeBuffer(&buffer);
Packit Service 75d76b
    FREE(block);
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  // Checksum everything decoded so far.
Packit Service 75d76b
  CRC32Checksum checksum = layer->updateCRC32(INITIAL_CHECKSUM, block,
Packit Service 75d76b
                                              uncompactedAmount(buffer));
Packit Service 75d76b
  CRC32Checksum savedChecksum;
Packit Service 75d76b
  result = getUInt32LEFromBuffer(buffer, &savedChecksum);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    freeBuffer(&buffer);
Packit Service 75d76b
    FREE(block);
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  // Finished all decoding. Everything that follows is validation code.
Packit Service 75d76b
  freeBuffer(&buffer);
Packit Service 75d76b
  FREE(block);
Packit Service 75d76b
Packit Service 75d76b
  if (!isLoadableReleaseVersion(geometry->releaseVersion)) {
Packit Service 75d76b
    return logErrorWithStringError(VDO_UNSUPPORTED_VERSION,
Packit Service 75d76b
                                   "release version %d cannot be loaded",
Packit Service 75d76b
                                   geometry->releaseVersion);
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  return ((checksum == savedChecksum) ? VDO_SUCCESS : VDO_CHECKSUM_MISMATCH);
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/************************************************************************/
Packit Service 75d76b
int computeIndexBlocks(IndexConfig *indexConfig, BlockCount *indexBlocksPtr)
Packit Service 75d76b
{
Packit Service 75d76b
  UdsConfiguration udsConfiguration = NULL;
Packit Service 75d76b
  int result = indexConfigToUdsConfiguration(indexConfig, &udsConfiguration);
Packit Service 75d76b
  if (result != UDS_SUCCESS) {
Packit Service 75d76b
    return logErrorWithStringError(result, "error creating index config");
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  uint64_t indexBytes;
Packit Service 75d76b
  result = udsComputeIndexSize(udsConfiguration, 0, &indexBytes);
Packit Service 75d76b
  udsFreeConfiguration(udsConfiguration);
Packit Service 75d76b
  if (result != UDS_SUCCESS) {
Packit Service 75d76b
    return logErrorWithStringError(result, "error computing index size");
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  BlockCount indexBlocks = indexBytes / VDO_BLOCK_SIZE;
Packit Service 75d76b
  if ((((uint64_t) indexBlocks) * VDO_BLOCK_SIZE) != indexBytes) {
Packit Service 75d76b
    return logErrorWithStringError(VDO_PARAMETER_MISMATCH, "index size must be"
Packit Service 75d76b
                                   " a multiple of block size %d",
Packit Service 75d76b
                                   VDO_BLOCK_SIZE);
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  *indexBlocksPtr = indexBlocks;
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
int initializeVolumeGeometry(Nonce           nonce,
Packit Service 75d76b
                             UUID            uuid,
Packit Service 75d76b
                             IndexConfig    *indexConfig,
Packit Service 75d76b
                             VolumeGeometry *geometry)
Packit Service 75d76b
{
Packit Service 75d76b
  BlockCount indexSize = 0;
Packit Service 75d76b
  if (indexConfig != NULL) {
Packit Service 75d76b
    int result = computeIndexBlocks(indexConfig, &indexSize);
Packit Service 75d76b
    if (result != VDO_SUCCESS) {
Packit Service 75d76b
      return result;
Packit Service 75d76b
    }
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  *geometry = (VolumeGeometry) {
Packit Service 75d76b
    .releaseVersion = CURRENT_RELEASE_VERSION_NUMBER,
Packit Service 75d76b
    .nonce = nonce,
Packit Service 75d76b
    .regions = {
Packit Service 75d76b
      [INDEX_REGION] = {
Packit Service 75d76b
        .id = INDEX_REGION,
Packit Service 75d76b
        .startBlock = 1,
Packit Service 75d76b
      },
Packit Service 75d76b
      [DATA_REGION] = {
Packit Service 75d76b
        .id = DATA_REGION,
Packit Service 75d76b
        .startBlock = 1 + indexSize,
Packit Service 75d76b
      }
Packit Service 75d76b
    }
Packit Service 75d76b
  };
Packit Service 75d76b
  memcpy(geometry->uuid, uuid, sizeof(UUID));
Packit Service 75d76b
  if (indexSize > 0) {
Packit Service 75d76b
    memcpy(&geometry->indexConfig, indexConfig, sizeof(IndexConfig));
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
int clearVolumeGeometry(PhysicalLayer *layer)
Packit Service 75d76b
{
Packit Service 75d76b
  char *block;
Packit Service 75d76b
  int result = layer->allocateIOBuffer(layer, VDO_BLOCK_SIZE, "geometry block",
Packit Service 75d76b
                                       &block);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = layer->writer(layer, GEOMETRY_BLOCK_LOCATION, 1, block, NULL);
Packit Service 75d76b
  FREE(block);
Packit Service 75d76b
  return result;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/**********************************************************************/
Packit Service 75d76b
int writeVolumeGeometry(PhysicalLayer *layer, VolumeGeometry *geometry)
Packit Service 75d76b
{
Packit Service 75d76b
  char *block;
Packit Service 75d76b
  int result = layer->allocateIOBuffer(layer, VDO_BLOCK_SIZE, "geometry block",
Packit Service 75d76b
                                       &block);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  Buffer *buffer;
Packit Service 75d76b
  result = wrapBuffer((byte *) block, VDO_BLOCK_SIZE, 0, &buffer);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    FREE(block);
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  result = encodeGeometryBlock(geometry, buffer);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    freeBuffer(&buffer);
Packit Service 75d76b
    FREE(block);
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  // Checksum everything encoded so far and then encode the checksum.
Packit Service 75d76b
  CRC32Checksum checksum = layer->updateCRC32(INITIAL_CHECKSUM, (byte *) block,
Packit Service 75d76b
                                              contentLength(buffer));
Packit Service 75d76b
  result = putUInt32LEIntoBuffer(buffer, checksum);
Packit Service 75d76b
  if (result != VDO_SUCCESS) {
Packit Service 75d76b
    freeBuffer(&buffer);
Packit Service 75d76b
    FREE(block);
Packit Service 75d76b
    return result;
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  // Write it.
Packit Service 75d76b
  result = layer->writer(layer, GEOMETRY_BLOCK_LOCATION, 1, block, NULL);
Packit Service 75d76b
  freeBuffer(&buffer);
Packit Service 75d76b
  FREE(block);
Packit Service 75d76b
  return result;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/************************************************************************/
Packit Service 75d76b
int indexConfigToUdsConfiguration(IndexConfig      *indexConfig,
Packit Service 75d76b
                                  UdsConfiguration *udsConfigPtr)
Packit Service 75d76b
{
Packit Service 75d76b
  UdsConfiguration udsConfiguration;
Packit Service 75d76b
  int result = udsInitializeConfiguration(&udsConfiguration, indexConfig->mem);
Packit Service 75d76b
  if (result != UDS_SUCCESS) {
Packit Service 75d76b
    return logErrorWithStringError(result, "error initializing configuration");
Packit Service 75d76b
  }
Packit Service 75d76b
Packit Service 75d76b
  udsConfigurationSetSparse(udsConfiguration, indexConfig->sparse);
Packit Service 75d76b
Packit Service 75d76b
  *udsConfigPtr = udsConfiguration;
Packit Service 75d76b
  return VDO_SUCCESS;
Packit Service 75d76b
}
Packit Service 75d76b
Packit Service 75d76b
/************************************************************************/
Packit Service 75d76b
void indexConfigToUdsParameters(IndexConfig           *indexConfig,
Packit Service 75d76b
                                struct uds_parameters *userParams)
Packit Service 75d76b
{
Packit Service 75d76b
  userParams->checkpoint_frequency = indexConfig->checkpointFrequency;
Packit Service 75d76b
}