|
Packit |
b55c50 |
/*
|
|
Packit |
b55c50 |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* This program is free software; you can redistribute it and/or
|
|
Packit |
b55c50 |
* modify it under the terms of the GNU General Public License
|
|
Packit |
b55c50 |
* as published by the Free Software Foundation; either version 2
|
|
Packit |
b55c50 |
* of the License, or (at your option) any later version.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
b55c50 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
b55c50 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
b55c50 |
* GNU General Public License for more details.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
b55c50 |
* along with this program; if not, write to the Free Software
|
|
Packit |
b55c50 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit |
b55c50 |
* 02110-1301, USA.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/blockMapEntry.h#4 $
|
|
Packit |
b55c50 |
*/
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
#ifndef BLOCK_MAP_ENTRY_H
|
|
Packit |
b55c50 |
#define BLOCK_MAP_ENTRY_H
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
#include "blockMappingState.h"
|
|
Packit |
b55c50 |
#include "constants.h"
|
|
Packit |
b55c50 |
#include "numeric.h"
|
|
Packit |
b55c50 |
#include "types.h"
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* The entry for each logical block in the block map is encoded into five
|
|
Packit |
b55c50 |
* bytes, which saves space in both the on-disk and in-memory layouts. It
|
|
Packit |
b55c50 |
* consists of the 36 low-order bits of a PhysicalBlockNumber (addressing 256
|
|
Packit |
b55c50 |
* terabytes with a 4KB block size) and a 4-bit encoding of a
|
|
Packit |
b55c50 |
* BlockMappingState.
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
typedef union __attribute__((packed)) blockMapEntry {
|
|
Packit |
b55c50 |
struct __attribute__((packed)) {
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Bits 7..4: The four highest bits of the 36-bit physical block number
|
|
Packit |
b55c50 |
* Bits 3..0: The 4-bit BlockMappingState
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
Packit |
b55c50 |
unsigned mappingState : 4;
|
|
Packit |
b55c50 |
unsigned pbnHighNibble : 4;
|
|
Packit |
b55c50 |
#else
|
|
Packit |
b55c50 |
unsigned pbnHighNibble : 4;
|
|
Packit |
b55c50 |
unsigned mappingState : 4;
|
|
Packit |
b55c50 |
#endif
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/** 32 low-order bits of the 36-bit PBN, in little-endian byte order */
|
|
Packit |
b55c50 |
byte pbnLowWord[4];
|
|
Packit |
b55c50 |
} fields;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
// A raw view of the packed encoding.
|
|
Packit |
b55c50 |
uint8_t raw[5];
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
Packit |
b55c50 |
// This view is only valid on little-endian machines and is only present for
|
|
Packit |
b55c50 |
// ease of directly examining packed entries in GDB.
|
|
Packit |
b55c50 |
struct __attribute__((packed)) {
|
|
Packit |
b55c50 |
unsigned mappingState : 4;
|
|
Packit |
b55c50 |
unsigned pbnHighNibble : 4;
|
|
Packit |
b55c50 |
uint32_t pbnLowWord;
|
|
Packit |
b55c50 |
} littleEndian;
|
|
Packit |
b55c50 |
#endif
|
|
Packit |
b55c50 |
} BlockMapEntry;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Unpack the fields of a BlockMapEntry, returning them as a DataLocation.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @param entry A pointer to the entry to unpack
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @return the location of the data mapped by the block map entry
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
static inline DataLocation unpackBlockMapEntry(const BlockMapEntry *entry)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
PhysicalBlockNumber low32 = getUInt32LE(entry->fields.pbnLowWord);
|
|
Packit |
b55c50 |
PhysicalBlockNumber high4 = entry->fields.pbnHighNibble;
|
|
Packit |
b55c50 |
return (DataLocation) {
|
|
Packit |
b55c50 |
.pbn = ((high4 << 32) | low32),
|
|
Packit |
b55c50 |
.state = entry->fields.mappingState,
|
|
Packit |
b55c50 |
};
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
static inline bool isMappedLocation(const DataLocation *location)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
return (location->state != MAPPING_STATE_UNMAPPED);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
static inline bool isValidLocation(const DataLocation *location)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
if (location->pbn == ZERO_BLOCK) {
|
|
Packit |
b55c50 |
return !isCompressed(location->state);
|
|
Packit |
b55c50 |
} else {
|
|
Packit |
b55c50 |
return isMappedLocation(location);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**
|
|
Packit |
b55c50 |
* Pack a PhysicalBlockNumber into a BlockMapEntry.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @param pbn The physical block number to convert to its
|
|
Packit |
b55c50 |
* packed five-byte representation
|
|
Packit |
b55c50 |
* @param mappingState The mapping state of the block
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @return the packed representation of the block number and mapping state
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* @note unrepresentable high bits of the unpacked PBN are silently truncated
|
|
Packit |
b55c50 |
**/
|
|
Packit |
b55c50 |
static inline BlockMapEntry packPBN(PhysicalBlockNumber pbn,
|
|
Packit |
b55c50 |
BlockMappingState mappingState)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
BlockMapEntry entry;
|
|
Packit |
b55c50 |
entry.fields.mappingState = (mappingState & 0x0F);
|
|
Packit |
b55c50 |
entry.fields.pbnHighNibble = ((pbn >> 32) & 0x0F),
|
|
Packit |
b55c50 |
storeUInt32LE(entry.fields.pbnLowWord, pbn & UINT_MAX);
|
|
Packit |
b55c50 |
return entry;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
#endif // BLOCK_MAP_ENTRY_H
|