Blame source/vdo/base/header.h

Packit Service d40955
/*
Packit Service d40955
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service d40955
 *
Packit Service d40955
 * This program is free software; you can redistribute it and/or
Packit Service d40955
 * modify it under the terms of the GNU General Public License
Packit Service d40955
 * as published by the Free Software Foundation; either version 2
Packit Service d40955
 * of the License, or (at your option) any later version.
Packit Service d40955
 * 
Packit Service d40955
 * This program is distributed in the hope that it will be useful,
Packit Service d40955
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service d40955
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service d40955
 * GNU General Public License for more details.
Packit Service d40955
 * 
Packit Service d40955
 * You should have received a copy of the GNU General Public License
Packit Service d40955
 * along with this program; if not, write to the Free Software
Packit Service d40955
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service d40955
 * 02110-1301, USA. 
Packit Service d40955
 *
Packit Service d40955
 * $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/header.h#4 $
Packit Service d40955
 */
Packit Service d40955
Packit Service d40955
#ifndef HEADER_H
Packit Service d40955
#define HEADER_H
Packit Service d40955
Packit Service d40955
#include "buffer.h"
Packit Service d40955
#include "numeric.h"
Packit Service d40955
Packit Service d40955
#include "types.h"
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * An in-memory representation of a version number for versioned structures on
Packit Service d40955
 * disk.
Packit Service d40955
 *
Packit Service d40955
 * A version number consists of two portions, a major version and a
Packit Service d40955
 * minor version. Any format change which does not require an explicit
Packit Service d40955
 * upgrade step from the previous version should increment the minor
Packit Service d40955
 * version. Any format change which either requires an explicit
Packit Service d40955
 * upgrade step, or is wholly incompatible (i.e. can not be upgraded
Packit Service d40955
 * to), should increment the major version, and set the minor version
Packit Service d40955
 * to 0.
Packit Service d40955
 **/
Packit Service d40955
typedef struct {
Packit Service d40955
  uint32_t majorVersion;
Packit Service d40955
  uint32_t minorVersion;
Packit Service d40955
} __attribute__((packed)) VersionNumber;
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * A packed, machine-independent, on-disk representation of a VersionNumber.
Packit Service d40955
 * Both fields are stored in little-endian byte order.
Packit Service d40955
 **/
Packit Service d40955
typedef struct {
Packit Service d40955
  byte majorVersion[4];
Packit Service d40955
  byte minorVersion[4];
Packit Service d40955
} __attribute__((packed)) PackedVersionNumber;
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * The registry of component ids for use in headers
Packit Service d40955
 **/
Packit Service d40955
typedef enum {
Packit Service d40955
  SUPER_BLOCK       = 0,
Packit Service d40955
  FIXED_LAYOUT      = 1,
Packit Service d40955
  RECOVERY_JOURNAL  = 2,
Packit Service d40955
  SLAB_DEPOT        = 3,
Packit Service d40955
  BLOCK_MAP         = 4,
Packit Service d40955
  GEOMETRY_BLOCK    = 5,
Packit Service d40955
} ComponentID;
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * The header for versioned data stored on disk.
Packit Service d40955
 **/
Packit Service d40955
typedef struct {
Packit Service d40955
  ComponentID         id;       // The component this is a header for
Packit Service d40955
  VersionNumber       version;  // The version of the data format
Packit Service d40955
  size_t              size;     // The size of the data following this header
Packit Service d40955
} __attribute__((packed)) Header;
Packit Service d40955
Packit Service d40955
enum {
Packit Service d40955
  ENCODED_HEADER_SIZE = sizeof(Header),
Packit Service d40955
};
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Check whether two version numbers are the same.
Packit Service d40955
 *
Packit Service d40955
 * @param versionA The first version
Packit Service d40955
 * @param versionB The second version
Packit Service d40955
 *
Packit Service d40955
 * @return true if the two versions are the same
Packit Service d40955
 **/
Packit Service d40955
static inline bool areSameVersion(VersionNumber versionA,
Packit Service d40955
                                  VersionNumber versionB)
Packit Service d40955
{
Packit Service d40955
  return ((versionA.majorVersion == versionB.majorVersion)
Packit Service d40955
          && (versionA.minorVersion == versionB.minorVersion));
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Check whether an actual version is upgradable to an expected version.
Packit Service d40955
 * An actual version is upgradable if its major number is expected but
Packit Service d40955
 * its minor number differs, and the expected version's minor number
Packit Service d40955
 * is greater than the actual version's minor number.
Packit Service d40955
 *
Packit Service d40955
 * @param expectedVersion The expected version
Packit Service d40955
 * @param actualVersion   The version being validated
Packit Service d40955
 *
Packit Service d40955
 * @return true if the actual version is upgradable
Packit Service d40955
 **/
Packit Service d40955
static inline bool isUpgradableVersion(VersionNumber expectedVersion,
Packit Service d40955
                                       VersionNumber actualVersion)
Packit Service d40955
{
Packit Service d40955
  return ((expectedVersion.majorVersion == actualVersion.majorVersion)
Packit Service d40955
          && (expectedVersion.minorVersion > actualVersion.minorVersion));
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Check whether a version matches an expected version. Logs an error
Packit Service d40955
 * describing a mismatch.
Packit Service d40955
 *
Packit Service d40955
 * @param expectedVersion  The expected version
Packit Service d40955
 * @param actualVersion    The version being validated
Packit Service d40955
 * @param componentName    The name of the component or the calling function
Packit Service d40955
 *                         (for error logging)
Packit Service d40955
 *
Packit Service d40955
 * @return VDO_SUCCESS             if the versions are the same
Packit Service d40955
 *         VDO_UNSUPPORTED_VERSION if the versions don't match
Packit Service d40955
 **/
Packit Service d40955
int validateVersion(VersionNumber  expectedVersion,
Packit Service d40955
                    VersionNumber  actualVersion,
Packit Service d40955
                    const char    *componentName)
Packit Service d40955
  __attribute__((warn_unused_result));
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Check whether a header matches expectations. Logs an error describing the
Packit Service d40955
 * first mismatch found.
Packit Service d40955
 *
Packit Service d40955
 * @param expectedHeader  The expected header
Packit Service d40955
 * @param actualHeader    The header being validated
Packit Service d40955
 * @param exactSize       If true, the size fields of the two headers must be
Packit Service d40955
 *                        the same, otherwise actualSize >= expectedSize is OK
Packit Service d40955
 * @param componentName   The name of the component or the calling function
Packit Service d40955
 *                        (for error logging)
Packit Service d40955
 *
Packit Service d40955
 * @return VDO_SUCCESS             if the header meets expectations
Packit Service d40955
 *         VDO_INCORRECT_COMPONENT if the component ids don't match
Packit Service d40955
 *         VDO_UNSUPPORTED_VERSION if the versions or sizes don't match
Packit Service d40955
 **/
Packit Service d40955
int validateHeader(const Header *expectedHeader,
Packit Service d40955
                   const Header *actualHeader,
Packit Service d40955
                   bool          exactSize,
Packit Service d40955
                   const char   *componentName)
Packit Service d40955
  __attribute__((warn_unused_result));
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Encode a header into a buffer.
Packit Service d40955
 *
Packit Service d40955
 * @param header  The header to encode
Packit Service d40955
 * @param buffer  The buffer in which to encode the header
Packit Service d40955
 *
Packit Service d40955
 * @return UDS_SUCCESS or an error
Packit Service d40955
 **/
Packit Service d40955
int encodeHeader(const Header *header, Buffer *buffer)
Packit Service d40955
  __attribute__((warn_unused_result));
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Encode a version number into a buffer.
Packit Service d40955
 *
Packit Service d40955
 * @param version  The version to encode
Packit Service d40955
 * @param buffer   The buffer in which to encode the version
Packit Service d40955
 *
Packit Service d40955
 * @return UDS_SUCCESS or an error
Packit Service d40955
 **/
Packit Service d40955
int encodeVersionNumber(VersionNumber version, Buffer *buffer)
Packit Service d40955
  __attribute__((warn_unused_result));
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Decode a header from a buffer.
Packit Service d40955
 *
Packit Service d40955
 * @param [in]  buffer  The buffer from which to decode the header
Packit Service d40955
 * @param [out] header  The header to decode
Packit Service d40955
 *
Packit Service d40955
 * @return UDS_SUCCESS or an error
Packit Service d40955
 **/
Packit Service d40955
int decodeHeader(Buffer *buffer, Header *header)
Packit Service d40955
  __attribute__((warn_unused_result));
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Decode a version number from a buffer.
Packit Service d40955
 *
Packit Service d40955
 * @param buffer   The buffer from which to decode the version
Packit Service d40955
 * @param version  The version structure to decode into
Packit Service d40955
 *
Packit Service d40955
 * @return UDS_SUCCESS or an error
Packit Service d40955
 **/
Packit Service d40955
int decodeVersionNumber(Buffer *buffer, VersionNumber *version)
Packit Service d40955
  __attribute__((warn_unused_result));
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Convert a VersionNumber to its packed on-disk representation.
Packit Service d40955
 *
Packit Service d40955
 * @param version  The version number to convert
Packit Service d40955
 *
Packit Service d40955
 * @return the platform-independent representation of the version
Packit Service d40955
 **/
Packit Service d40955
static inline PackedVersionNumber packVersionNumber(VersionNumber version)
Packit Service d40955
{
Packit Service d40955
  PackedVersionNumber packed;
Packit Service d40955
  storeUInt32LE(packed.majorVersion, version.majorVersion);
Packit Service d40955
  storeUInt32LE(packed.minorVersion, version.minorVersion);
Packit Service d40955
  return packed;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**
Packit Service d40955
 * Convert a PackedVersionNumber to its native in-memory representation.
Packit Service d40955
 *
Packit Service d40955
 * @param version  The version number to convert
Packit Service d40955
 *
Packit Service d40955
 * @return the platform-independent representation of the version
Packit Service d40955
 **/
Packit Service d40955
static inline VersionNumber unpackVersionNumber(PackedVersionNumber version)
Packit Service d40955
{
Packit Service d40955
  return (VersionNumber) {
Packit Service d40955
    .majorVersion = getUInt32LE(version.majorVersion),
Packit Service d40955
    .minorVersion = getUInt32LE(version.minorVersion),
Packit Service d40955
  };
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
#endif // HEADER_H