|
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/packedRecoveryJournalBlock.h#3 $
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#ifndef PACKED_RECOVERY_JOURNAL_BLOCK_H
|
|
Packit Service |
d40955 |
#define PACKED_RECOVERY_JOURNAL_BLOCK_H
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include "numeric.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include "constants.h"
|
|
Packit Service |
d40955 |
#include "recoveryJournalEntry.h"
|
|
Packit Service |
d40955 |
#include "types.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
typedef struct {
|
|
Packit Service |
d40955 |
SequenceNumber blockMapHead; // Block map head sequence number
|
|
Packit Service |
d40955 |
SequenceNumber slabJournalHead; // Slab journal head sequence number
|
|
Packit Service |
d40955 |
SequenceNumber sequenceNumber; // Sequence number for this block
|
|
Packit Service |
d40955 |
Nonce nonce; // A given VDO instance's nonce
|
|
Packit Service |
d40955 |
BlockCount logicalBlocksUsed; // Count of logical blocks in use
|
|
Packit Service |
d40955 |
BlockCount blockMapDataBlocks; // Count of allocated block map pages
|
|
Packit Service |
d40955 |
JournalEntryCount entryCount; // Number of entries written
|
|
Packit Service |
d40955 |
uint8_t checkByte; // The protection check byte
|
|
Packit Service |
d40955 |
uint8_t recoveryCount; // The number of recoveries completed
|
|
Packit Service |
d40955 |
VDOMetadataType metadataType; // Metadata type
|
|
Packit Service |
d40955 |
} RecoveryBlockHeader;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* The packed, on-disk representation of a recovery journal block header.
|
|
Packit Service |
d40955 |
* All fields are kept in little-endian byte order.
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
typedef union __attribute__((packed)) {
|
|
Packit Service |
d40955 |
struct __attribute__((packed)) {
|
|
Packit Service |
d40955 |
/** Block map head 64-bit sequence number */
|
|
Packit Service |
d40955 |
byte blockMapHead[8];
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** Slab journal head 64-bit sequence number */
|
|
Packit Service |
d40955 |
byte slabJournalHead[8];
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** The 64-bit sequence number for this block */
|
|
Packit Service |
d40955 |
byte sequenceNumber[8];
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** A given VDO instance's 64-bit nonce */
|
|
Packit Service |
d40955 |
byte nonce[8];
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** 8-bit metadata type (should always be one for the recovery journal) */
|
|
Packit Service |
d40955 |
uint8_t metadataType;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** 16-bit count of the entries encoded in the block */
|
|
Packit Service |
d40955 |
byte entryCount[2];
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** 64-bit count of the logical blocks used when this block was opened */
|
|
Packit Service |
d40955 |
byte logicalBlocksUsed[8];
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** 64-bit count of the block map blocks used when this block was opened */
|
|
Packit Service |
d40955 |
byte blockMapDataBlocks[8];
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** The protection check byte */
|
|
Packit Service |
d40955 |
uint8_t checkByte;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** The number of recoveries completed */
|
|
Packit Service |
d40955 |
uint8_t recoveryCount;
|
|
Packit Service |
d40955 |
} fields;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
// A raw view of the packed encoding.
|
|
Packit Service |
d40955 |
uint8_t raw[8 + 8 + 8 + 8 + 1 + 2 + 8 + 8 + 1 + 1];
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
Packit Service |
d40955 |
// This view is only valid on little-endian machines and is only present for
|
|
Packit Service |
d40955 |
// ease of directly examining packed entries in GDB.
|
|
Packit Service |
d40955 |
struct __attribute__((packed)) {
|
|
Packit Service |
d40955 |
SequenceNumber blockMapHead;
|
|
Packit Service |
d40955 |
SequenceNumber slabJournalHead;
|
|
Packit Service |
d40955 |
SequenceNumber sequenceNumber;
|
|
Packit Service |
d40955 |
Nonce nonce;
|
|
Packit Service |
d40955 |
VDOMetadataType metadataType;
|
|
Packit Service |
d40955 |
JournalEntryCount entryCount;
|
|
Packit Service |
d40955 |
BlockCount logicalBlocksUsed;
|
|
Packit Service |
d40955 |
BlockCount blockMapDataBlocks;
|
|
Packit Service |
d40955 |
uint8_t checkByte;
|
|
Packit Service |
d40955 |
uint8_t recoveryCount;
|
|
Packit Service |
d40955 |
} littleEndian;
|
|
Packit Service |
d40955 |
#endif
|
|
Packit Service |
d40955 |
} PackedJournalHeader;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
typedef struct {
|
|
Packit Service |
d40955 |
/** The protection check byte */
|
|
Packit Service |
d40955 |
uint8_t checkByte;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** The number of recoveries completed */
|
|
Packit Service |
d40955 |
uint8_t recoveryCount;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** The number of entries in this sector */
|
|
Packit Service |
d40955 |
uint8_t entryCount;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/** Journal entries for this sector */
|
|
Packit Service |
d40955 |
PackedRecoveryJournalEntry entries[];
|
|
Packit Service |
d40955 |
} __attribute__((packed)) PackedJournalSector;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
enum {
|
|
Packit Service |
d40955 |
// Allowing more than 311 entries in each block changes the math
|
|
Packit Service |
d40955 |
// concerning the amortization of metadata writes and recovery speed.
|
|
Packit Service |
d40955 |
RECOVERY_JOURNAL_ENTRIES_PER_BLOCK = 311,
|
|
Packit Service |
d40955 |
/** The number of entries in each sector (except the last) when filled */
|
|
Packit Service |
d40955 |
RECOVERY_JOURNAL_ENTRIES_PER_SECTOR
|
|
Packit Service |
d40955 |
= ((VDO_SECTOR_SIZE - sizeof(PackedJournalSector))
|
|
Packit Service |
d40955 |
/ sizeof(PackedRecoveryJournalEntry)),
|
|
Packit Service |
d40955 |
/** The number of entries in the last sector when a block is full */
|
|
Packit Service |
d40955 |
RECOVERY_JOURNAL_ENTRIES_PER_LAST_SECTOR
|
|
Packit Service |
d40955 |
= (RECOVERY_JOURNAL_ENTRIES_PER_BLOCK
|
|
Packit Service |
d40955 |
% RECOVERY_JOURNAL_ENTRIES_PER_SECTOR),
|
|
Packit Service |
d40955 |
};
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Find the recovery journal sector from the block header and sector number.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param header The header of the recovery journal block
|
|
Packit Service |
d40955 |
* @param sectorNumber The index of the sector (1-based)
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return A packed recovery journal sector
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
__attribute__((warn_unused_result))
|
|
Packit Service |
d40955 |
static inline
|
|
Packit Service |
d40955 |
PackedJournalSector *getJournalBlockSector(PackedJournalHeader *header,
|
|
Packit Service |
d40955 |
int sectorNumber)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
char *sectorData = ((char *) header) + (VDO_SECTOR_SIZE * sectorNumber);
|
|
Packit Service |
d40955 |
return (PackedJournalSector *) sectorData;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Generate the packed representation of a recovery block header.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param header The header containing the values to encode
|
|
Packit Service |
d40955 |
* @param packed The header into which to pack the values
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline void packRecoveryBlockHeader(const RecoveryBlockHeader *header,
|
|
Packit Service |
d40955 |
PackedJournalHeader *packed)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
storeUInt64LE(packed->fields.blockMapHead, header->blockMapHead);
|
|
Packit Service |
d40955 |
storeUInt64LE(packed->fields.slabJournalHead, header->slabJournalHead);
|
|
Packit Service |
d40955 |
storeUInt64LE(packed->fields.sequenceNumber, header->sequenceNumber);
|
|
Packit Service |
d40955 |
storeUInt64LE(packed->fields.nonce, header->nonce);
|
|
Packit Service |
d40955 |
storeUInt64LE(packed->fields.logicalBlocksUsed, header->logicalBlocksUsed);
|
|
Packit Service |
d40955 |
storeUInt64LE(packed->fields.blockMapDataBlocks, header->blockMapDataBlocks);
|
|
Packit Service |
d40955 |
storeUInt16LE(packed->fields.entryCount, header->entryCount);
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
packed->fields.checkByte = header->checkByte;
|
|
Packit Service |
d40955 |
packed->fields.recoveryCount = header->recoveryCount;
|
|
Packit Service |
d40955 |
packed->fields.metadataType = header->metadataType;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Decode the packed representation of a recovery block header.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param packed The packed header to decode
|
|
Packit Service |
d40955 |
* @param header The header into which to unpack the values
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline void unpackRecoveryBlockHeader(const PackedJournalHeader *packed,
|
|
Packit Service |
d40955 |
RecoveryBlockHeader *header)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
*header = (RecoveryBlockHeader) {
|
|
Packit Service |
d40955 |
.blockMapHead = getUInt64LE(packed->fields.blockMapHead),
|
|
Packit Service |
d40955 |
.slabJournalHead = getUInt64LE(packed->fields.slabJournalHead),
|
|
Packit Service |
d40955 |
.sequenceNumber = getUInt64LE(packed->fields.sequenceNumber),
|
|
Packit Service |
d40955 |
.nonce = getUInt64LE(packed->fields.nonce),
|
|
Packit Service |
d40955 |
.logicalBlocksUsed = getUInt64LE(packed->fields.logicalBlocksUsed),
|
|
Packit Service |
d40955 |
.blockMapDataBlocks = getUInt64LE(packed->fields.blockMapDataBlocks),
|
|
Packit Service |
d40955 |
.entryCount = getUInt16LE(packed->fields.entryCount),
|
|
Packit Service |
d40955 |
.checkByte = packed->fields.checkByte,
|
|
Packit Service |
d40955 |
.recoveryCount = packed->fields.recoveryCount,
|
|
Packit Service |
d40955 |
.metadataType = packed->fields.metadataType,
|
|
Packit Service |
d40955 |
};
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#endif // PACKED_RECOVERY_JOURNAL_BLOCK_H
|