Blame source/vdo/base/header.h

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