|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
310c69 |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
310c69 |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
310c69 |
* of the License, or (at your option) any later version.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
310c69 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
310c69 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
310c69 |
* GNU General Public License for more details.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
310c69 |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
310c69 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
310c69 |
* 02110-1301, USA.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* $Id: //eng/uds-releases/jasper/src/uds/indexLayout.c#19 $
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "indexLayout.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "buffer.h"
|
|
Packit Service |
310c69 |
#include "compiler.h"
|
|
Packit Service |
310c69 |
#include "config.h"
|
|
Packit Service |
310c69 |
#include "indexConfig.h"
|
|
Packit Service |
310c69 |
#include "layoutRegion.h"
|
|
Packit Service |
310c69 |
#include "logger.h"
|
|
Packit Service |
310c69 |
#include "masterIndexOps.h"
|
|
Packit Service |
310c69 |
#include "memoryAlloc.h"
|
|
Packit Service |
310c69 |
#include "nonce.h"
|
|
Packit Service |
310c69 |
#include "openChapter.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* Overall layout of an index on disk:
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* The layout is divided into a number of fixed-size regions, the sizes of
|
|
Packit Service |
310c69 |
* which are computed when the index is created. Every header and region
|
|
Packit Service |
310c69 |
* begins on 4K block boundary. Save regions are further sub-divided into
|
|
Packit Service |
310c69 |
* regions of their own.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* Each region has a kind and an instance number. Some kinds only have one
|
|
Packit Service |
310c69 |
* instance and therefore use RL_SOLE_INSTANCE (-1) as the instance number.
|
|
Packit Service |
310c69 |
* The RL_KIND_INDEX uses instances to represent sub-indices, where used.
|
|
Packit Service |
310c69 |
* A save region can either hold a checkpoint or a clean shutdown (determined
|
|
Packit Service |
310c69 |
* by the type). The instances determine which available save slot is used.
|
|
Packit Service |
310c69 |
* The RL_KIND_MASTER_INDEX uses instances to record which zone is being saved.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* +-+-+--------+--------+--------+-----+--- -+-+
|
|
Packit Service |
310c69 |
* | | | I N D E X 0 101, 0 | ... | |
|
|
Packit Service |
310c69 |
* |H|C+--------+--------+--------+-----+--- -+S|
|
|
Packit Service |
310c69 |
* |D|f| Volume | Save | Save | | |e|
|
|
Packit Service |
310c69 |
* |R|g| Region | Region | Region | ... | ... |a|
|
|
Packit Service |
310c69 |
* | | | 201 -1 | 202 0 | 202 1 | | |l|
|
|
Packit Service |
310c69 |
* +-+-+--------+--------+--------+-----+--- -+-+
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* The header contains the encoded regional layout table as well as
|
|
Packit Service |
310c69 |
* the saved index configuration record. The sub-index regions and their
|
|
Packit Service |
310c69 |
* subdivisions are maintained in the same table.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* There are at least two save regions per sub-index to preserve the old
|
|
Packit Service |
310c69 |
* state should the saving of a state be incomplete. They are used in
|
|
Packit Service |
310c69 |
* a round-robin fashion.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* Anatomy of a save region:
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* +-+-----+------+------+-----+ -+-----+
|
|
Packit Service |
310c69 |
* |H| IPM | MI | MI | | | OC |
|
|
Packit Service |
310c69 |
* |D| | zone | zone | ... | | |
|
|
Packit Service |
310c69 |
* |R| 301 | 302 | 302 | | | 303 |
|
|
Packit Service |
310c69 |
* | | -1 | 0 | 1 | | | -1 |
|
|
Packit Service |
310c69 |
* +-+-----+------+------+-----+ -+-----+
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* Every region header has a type (and version). In save regions,
|
|
Packit Service |
310c69 |
* the open chapter only appears in RL_TYPE_SAVE not RL_TYPE_CHECKPOINT,
|
|
Packit Service |
310c69 |
* although the same space is reserved for both.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* The header contains the encoded regional layout table as well as the
|
|
Packit Service |
310c69 |
* index state record for that save or checkpoint. Each save or checkpoint
|
|
Packit Service |
310c69 |
* has a unique generation number and nonce which is used to seed the
|
|
Packit Service |
310c69 |
* checksums of those regions.
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct indexSaveData_v1 {
|
|
Packit Service |
310c69 |
uint64_t timestamp; // ms since epoch...
|
|
Packit Service |
310c69 |
uint64_t nonce;
|
|
Packit Service |
310c69 |
uint32_t version; // 1
|
|
Packit Service |
310c69 |
uint32_t unused__;
|
|
Packit Service |
310c69 |
} IndexSaveData;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct indexSaveLayout {
|
|
Packit Service |
310c69 |
LayoutRegion indexSave;
|
|
Packit Service |
310c69 |
LayoutRegion header;
|
|
Packit Service |
310c69 |
unsigned int numZones;
|
|
Packit Service |
310c69 |
LayoutRegion indexPageMap;
|
|
Packit Service |
310c69 |
LayoutRegion freeSpace;
|
|
Packit Service |
310c69 |
LayoutRegion *masterIndexZones;
|
|
Packit Service |
310c69 |
LayoutRegion *openChapter;
|
|
Packit Service |
310c69 |
IndexSaveType saveType;
|
|
Packit Service |
310c69 |
IndexSaveData saveData;
|
|
Packit Service |
310c69 |
Buffer *indexStateBuffer;
|
|
Packit Service |
310c69 |
bool read;
|
|
Packit Service |
310c69 |
bool written;
|
|
Packit Service |
310c69 |
} IndexSaveLayout;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct subIndexLayout {
|
|
Packit Service |
310c69 |
LayoutRegion subIndex;
|
|
Packit Service |
310c69 |
uint64_t nonce;
|
|
Packit Service |
310c69 |
LayoutRegion volume;
|
|
Packit Service |
310c69 |
IndexSaveLayout *saves;
|
|
Packit Service |
310c69 |
} SubIndexLayout;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct superBlockData_v1 {
|
|
Packit Service |
310c69 |
byte magicLabel[32];
|
|
Packit Service |
310c69 |
byte nonceInfo[32];
|
|
Packit Service |
310c69 |
uint64_t nonce;
|
|
Packit Service |
310c69 |
uint32_t version; // 2
|
|
Packit Service |
310c69 |
uint32_t blockSize; // for verification
|
|
Packit Service |
310c69 |
uint16_t numIndexes; // 1
|
|
Packit Service |
310c69 |
uint16_t maxSaves;
|
|
Packit Service |
310c69 |
uint64_t openChapterBlocks;
|
|
Packit Service |
310c69 |
uint64_t pageMapBlocks;
|
|
Packit Service |
310c69 |
} SuperBlockData;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
struct indexLayout {
|
|
Packit Service |
310c69 |
IOFactory *factory;
|
|
Packit Service |
310c69 |
off_t offset;
|
|
Packit Service |
310c69 |
struct index_version indexVersion;
|
|
Packit Service |
310c69 |
SuperBlockData super;
|
|
Packit Service |
310c69 |
LayoutRegion header;
|
|
Packit Service |
310c69 |
LayoutRegion config;
|
|
Packit Service |
310c69 |
SubIndexLayout index;
|
|
Packit Service |
310c69 |
LayoutRegion seal;
|
|
Packit Service |
310c69 |
uint64_t totalBlocks;
|
|
Packit Service |
310c69 |
int refCount;
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Structure used to compute single file layout sizes.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* Note that the masterIndexBlocks represent all zones and are sized for
|
|
Packit Service |
310c69 |
* the maximum number of blocks that would be needed regardless of the number
|
|
Packit Service |
310c69 |
* of zones (up to the maximum value) that are used at run time.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* Similarly, the number of saves is sized for the minimum safe value
|
|
Packit Service |
310c69 |
* assuming checkpointing is enabled, since that is also a run-time parameter.
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
typedef struct saveLayoutSizes {
|
|
Packit Service |
310c69 |
Configuration config; // this is a captive copy
|
|
Packit Service |
310c69 |
Geometry geometry; // this is a captive copy
|
|
Packit Service |
310c69 |
unsigned int numSaves; // per sub-index
|
|
Packit Service |
310c69 |
size_t blockSize; // in bytes
|
|
Packit Service |
310c69 |
uint64_t volumeBlocks; // per sub-index
|
|
Packit Service |
310c69 |
uint64_t masterIndexBlocks; // per save
|
|
Packit Service |
310c69 |
uint64_t pageMapBlocks; // per save
|
|
Packit Service |
310c69 |
uint64_t openChapterBlocks; // per save
|
|
Packit Service |
310c69 |
uint64_t saveBlocks; // per sub-index
|
|
Packit Service |
310c69 |
uint64_t subIndexBlocks; // per sub-index
|
|
Packit Service |
310c69 |
uint64_t totalBlocks; // for whole layout
|
|
Packit Service |
310c69 |
} SaveLayoutSizes;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
enum {
|
|
Packit Service |
310c69 |
INDEX_STATE_BUFFER_SIZE = 512,
|
|
Packit Service |
310c69 |
MAX_SAVES = 5,
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
static const byte SINGLE_FILE_MAGIC_1[32] = "*ALBIREO*SINGLE*FILE*LAYOUT*001*";
|
|
Packit Service |
310c69 |
enum {
|
|
Packit Service |
310c69 |
SINGLE_FILE_MAGIC_1_LENGTH = sizeof(SINGLE_FILE_MAGIC_1),
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
static int reconstituteSingleFileLayout(IndexLayout *layout,
|
|
Packit Service |
310c69 |
SuperBlockData *super,
|
|
Packit Service |
310c69 |
RegionTable *table,
|
|
Packit Service |
310c69 |
uint64_t firstBlock)
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result));
|
|
Packit Service |
310c69 |
static int writeIndexSaveLayout(IndexLayout *layout, IndexSaveLayout *isl)
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result));
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
static INLINE uint64_t blockCount(uint64_t bytes, uint32_t blockSize)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
uint64_t blocks = bytes / blockSize;
|
|
Packit Service |
310c69 |
if (bytes % blockSize > 0) {
|
|
Packit Service |
310c69 |
++blocks;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return blocks;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int computeSizes(SaveLayoutSizes *sls,
|
|
Packit Service |
310c69 |
const UdsConfiguration config,
|
|
Packit Service |
310c69 |
size_t blockSize,
|
|
Packit Service |
310c69 |
unsigned int numCheckpoints)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (config->bytesPerPage % blockSize != 0) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_INCORRECT_ALIGNMENT,
|
|
Packit Service |
310c69 |
"page size not a multiple of block size");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
Configuration *cfg = NULL;
|
|
Packit Service |
310c69 |
int result = makeConfiguration(config, &cfg;;
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result, "cannot compute layout size");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
memset(sls, 0, sizeof(*sls));
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// internalize the configuration and geometry...
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
sls->geometry = *cfg->geometry;
|
|
Packit Service |
310c69 |
sls->config = *cfg;
|
|
Packit Service |
310c69 |
sls->config.geometry = &sls->geometry;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
freeConfiguration(cfg);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
sls->numSaves = 2 + numCheckpoints;
|
|
Packit Service |
310c69 |
sls->blockSize = blockSize;
|
|
Packit Service |
310c69 |
sls->volumeBlocks = sls->geometry.bytesPerVolume / blockSize;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = computeMasterIndexSaveBlocks(&sls->config, blockSize,
|
|
Packit Service |
310c69 |
&sls->masterIndexBlocks);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result, "cannot compute index save size");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
sls->pageMapBlocks =
|
|
Packit Service |
310c69 |
blockCount(computeIndexPageMapSaveSize(&sls->geometry), blockSize);
|
|
Packit Service |
310c69 |
sls->openChapterBlocks =
|
|
Packit Service |
310c69 |
blockCount(computeSavedOpenChapterSize(&sls->geometry), blockSize);
|
|
Packit Service |
310c69 |
sls->saveBlocks = 1 + (sls->masterIndexBlocks +
|
|
Packit Service |
310c69 |
sls->pageMapBlocks + sls->openChapterBlocks);
|
|
Packit Service |
310c69 |
sls->subIndexBlocks = sls->volumeBlocks + (sls->numSaves * sls->saveBlocks);
|
|
Packit Service |
310c69 |
sls->totalBlocks = 3 + sls->subIndexBlocks;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int udsComputeIndexSize(const UdsConfiguration config,
|
|
Packit Service |
310c69 |
unsigned int numCheckpoints,
|
|
Packit Service |
310c69 |
uint64_t *indexSize)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
SaveLayoutSizes sizes;
|
|
Packit Service |
310c69 |
int result = computeSizes(&sizes, config, UDS_BLOCK_SIZE, numCheckpoints);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (indexSize != NULL) {
|
|
Packit Service |
310c69 |
*indexSize = sizes.totalBlocks * sizes.blockSize;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int openLayoutReader(IndexLayout *layout,
|
|
Packit Service |
310c69 |
LayoutRegion *lr,
|
|
Packit Service |
310c69 |
BufferedReader **readerPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
off_t start = lr->startBlock * layout->super.blockSize;
|
|
Packit Service |
310c69 |
size_t size = lr->numBlocks * layout->super.blockSize;
|
|
Packit Service |
310c69 |
return openBufferedReader(layout->factory, start, size, readerPtr);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int openLayoutWriter(IndexLayout *layout,
|
|
Packit Service |
310c69 |
LayoutRegion *lr,
|
|
Packit Service |
310c69 |
BufferedWriter **writerPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
off_t start = lr->startBlock * layout->super.blockSize;
|
|
Packit Service |
310c69 |
size_t size = lr->numBlocks * layout->super.blockSize;
|
|
Packit Service |
310c69 |
return openBufferedWriter(layout->factory, start, size, writerPtr);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int decodeIndexSaveData(Buffer *buffer, IndexSaveData *saveData)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = getUInt64LEFromBuffer(buffer, &saveData->timestamp);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt64LEFromBuffer(buffer, &saveData->nonce);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt32LEFromBuffer(buffer, &saveData->version);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt32LEFromBuffer(buffer, &saveData->unused__);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
// The unused padding has to be zeroed for correct nonce calculation
|
|
Packit Service |
310c69 |
if (saveData->unused__ != 0) {
|
|
Packit Service |
310c69 |
return UDS_CORRUPT_COMPONENT;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = ASSERT_LOG_ONLY(contentLength(buffer) == 0,
|
|
Packit Service |
310c69 |
"%zu bytes decoded of %zu expected",
|
|
Packit Service |
310c69 |
bufferLength(buffer), sizeof(*saveData));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return UDS_CORRUPT_COMPONENT;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int decodeRegionHeader(Buffer *buffer, RegionHeader *header)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = getUInt64LEFromBuffer(buffer, &header->magic);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt64LEFromBuffer(buffer, &header->regionBlocks);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt16LEFromBuffer(buffer, &header->type);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt16LEFromBuffer(buffer, &header->version);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt16LEFromBuffer(buffer, &header->numRegions);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt16LEFromBuffer(buffer, &header->payload);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = ASSERT_LOG_ONLY(contentLength(buffer) == 0,
|
|
Packit Service |
310c69 |
"%zu bytes decoded of %zu expected",
|
|
Packit Service |
310c69 |
bufferLength(buffer), sizeof(*header));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return UDS_CORRUPT_COMPONENT;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int decodeLayoutRegion(Buffer *buffer, LayoutRegion *region)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
size_t cl1 = contentLength(buffer);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
int result = getUInt64LEFromBuffer(buffer, ®ion->startBlock);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt64LEFromBuffer(buffer, ®ion->numBlocks);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt32LEFromBuffer(buffer, ®ion->checksum);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt16LEFromBuffer(buffer, ®ion->kind);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt16LEFromBuffer(buffer, ®ion->instance);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = ASSERT_LOG_ONLY(cl1 - contentLength(buffer) == sizeof(*region),
|
|
Packit Service |
310c69 |
"%zu bytes decoded, of %zu expected",
|
|
Packit Service |
310c69 |
cl1 - contentLength(buffer), sizeof(*region));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return UDS_CORRUPT_COMPONENT;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int loadRegionTable(BufferedReader *reader, RegionTable **tablePtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
Buffer *buffer;
|
|
Packit Service |
310c69 |
int result = makeBuffer(sizeof(RegionHeader), &buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = readFromBufferedReader(reader, getBufferContents(buffer),
|
|
Packit Service |
310c69 |
bufferLength(buffer));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result, "cannot read region table header");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = resetBufferEnd(buffer, bufferLength(buffer));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
RegionHeader header;
|
|
Packit Service |
310c69 |
result = decodeRegionHeader(buffer, &header);
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (header.magic != REGION_MAGIC) {
|
|
Packit Service |
310c69 |
return UDS_NO_INDEX;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (header.version != 1) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_UNSUPPORTED_VERSION,
|
|
Packit Service |
310c69 |
"unknown region table version %" PRIu16,
|
|
Packit Service |
310c69 |
header.version);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
RegionTable *table;
|
|
Packit Service |
310c69 |
result = ALLOCATE_EXTENDED(RegionTable, header.numRegions, LayoutRegion,
|
|
Packit Service |
310c69 |
"single file layout region table", &table);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
table->header = header;
|
|
Packit Service |
310c69 |
result = makeBuffer(header.numRegions * sizeof(LayoutRegion), &buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = readFromBufferedReader(reader, getBufferContents(buffer),
|
|
Packit Service |
310c69 |
bufferLength(buffer));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_CORRUPT_COMPONENT,
|
|
Packit Service |
310c69 |
"cannot read region table layouts");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = resetBufferEnd(buffer, bufferLength(buffer));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
unsigned int i;
|
|
Packit Service |
310c69 |
for (i = 0; i < header.numRegions; i++){
|
|
Packit Service |
310c69 |
result = decodeLayoutRegion(buffer, &table->regions[i]);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
*tablePtr = table;
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int decodeSuperBlockData(Buffer *buffer, SuperBlockData *super)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = getBytesFromBuffer(buffer, 32, super->magicLabel);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getBytesFromBuffer(buffer, 32, super->nonceInfo);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt64LEFromBuffer(buffer, &super->nonce);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt32LEFromBuffer(buffer, &super->version);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt32LEFromBuffer(buffer, &super->blockSize);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt16LEFromBuffer(buffer, &super->numIndexes);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt16LEFromBuffer(buffer, &super->maxSaves);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = skipForward(buffer, 4); // aligment
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt64LEFromBuffer(buffer, &super->openChapterBlocks);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = getUInt64LEFromBuffer(buffer, &super->pageMapBlocks);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = ASSERT_LOG_ONLY(contentLength(buffer) == 0,
|
|
Packit Service |
310c69 |
"%zu bytes decoded of %zu expected",
|
|
Packit Service |
310c69 |
bufferLength(buffer), sizeof(*super));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return UDS_CORRUPT_COMPONENT;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int readSuperBlockData(BufferedReader *reader,
|
|
Packit Service |
310c69 |
SuperBlockData *super,
|
|
Packit Service |
310c69 |
size_t savedSize)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (savedSize != sizeof(SuperBlockData)) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_CORRUPT_COMPONENT,
|
|
Packit Service |
310c69 |
"unexpected super block data size %zu",
|
|
Packit Service |
310c69 |
savedSize);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (sizeof(super->magicLabel) != SINGLE_FILE_MAGIC_1_LENGTH) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_CORRUPT_COMPONENT,
|
|
Packit Service |
310c69 |
"super block magic label size incorrect");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
Buffer *buffer;
|
|
Packit Service |
310c69 |
int result = makeBuffer(savedSize, &buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = readFromBufferedReader(reader, getBufferContents(buffer),
|
|
Packit Service |
310c69 |
bufferLength(buffer));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result, "cannot read region table header");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = resetBufferEnd(buffer, bufferLength(buffer));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = decodeSuperBlockData(buffer, super);
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result, "cannot read super block data");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (memcmp(super->magicLabel, SINGLE_FILE_MAGIC_1,
|
|
Packit Service |
310c69 |
SINGLE_FILE_MAGIC_1_LENGTH) != 0) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_CORRUPT_COMPONENT,
|
|
Packit Service |
310c69 |
"unknown superblock magic label");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if ((super->version < SUPER_VERSION_MINIMUM)
|
|
Packit Service |
310c69 |
|| (super->version > SUPER_VERSION_MAXIMUM)) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_UNSUPPORTED_VERSION,
|
|
Packit Service |
310c69 |
"unknown superblock version number %"
|
|
Packit Service |
310c69 |
PRIu32,
|
|
Packit Service |
310c69 |
super->version);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// We dropped the usage of multiple subindices before we ever ran UDS code in
|
|
Packit Service |
310c69 |
// the kernel. We do not have code that will handle multiple subindices.
|
|
Packit Service |
310c69 |
if (super->numIndexes != 1) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_CORRUPT_COMPONENT,
|
|
Packit Service |
310c69 |
"invalid subindex count %" PRIu32,
|
|
Packit Service |
310c69 |
super->numIndexes);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (generateMasterNonce(super->nonceInfo, sizeof(super->nonceInfo)) !=
|
|
Packit Service |
310c69 |
super->nonce)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_CORRUPT_COMPONENT,
|
|
Packit Service |
310c69 |
"inconsistent superblock nonce");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int allocateSingleFileParts(IndexLayout *layout,
|
|
Packit Service |
310c69 |
SuperBlockData *super)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = ALLOCATE(super->maxSaves, IndexSaveLayout, __func__,
|
|
Packit Service |
310c69 |
&layout->index.saves);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int loadSuperBlock(IndexLayout *layout,
|
|
Packit Service |
310c69 |
size_t blockSize,
|
|
Packit Service |
310c69 |
uint64_t firstBlock,
|
|
Packit Service |
310c69 |
BufferedReader *reader)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
RegionTable *table = NULL;
|
|
Packit Service |
310c69 |
int result = loadRegionTable(reader, &table);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (table->header.type != RH_TYPE_SUPER) {
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_CORRUPT_COMPONENT,
|
|
Packit Service |
310c69 |
"not a superblock region table");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
SuperBlockData superBlockData;
|
|
Packit Service |
310c69 |
result = readSuperBlockData(reader, &superBlockData, table->header.payload);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result, "unknown superblock format");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (superBlockData.blockSize != blockSize) {
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_WRONG_INDEX_CONFIG,
|
|
Packit Service |
310c69 |
"superblock saved blockSize %" PRIu32
|
|
Packit Service |
310c69 |
" differs from supplied blockSize %zu",
|
|
Packit Service |
310c69 |
superBlockData.blockSize, blockSize);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
initializeIndexVersion(&layout->indexVersion, superBlockData.version);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = allocateSingleFileParts(layout, &superBlockData);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = reconstituteSingleFileLayout(layout, &superBlockData, table,
|
|
Packit Service |
310c69 |
firstBlock);
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int readIndexSaveData(BufferedReader *reader,
|
|
Packit Service |
310c69 |
IndexSaveData *saveData,
|
|
Packit Service |
310c69 |
size_t savedSize,
|
|
Packit Service |
310c69 |
Buffer **bufferPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = UDS_SUCCESS;
|
|
Packit Service |
310c69 |
if (savedSize == 0) {
|
|
Packit Service |
310c69 |
memset(saveData, 0, sizeof(*saveData));
|
|
Packit Service |
310c69 |
} else {
|
|
Packit Service |
310c69 |
if (savedSize < sizeof(IndexSaveData)) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_CORRUPT_COMPONENT,
|
|
Packit Service |
310c69 |
"unexpected index save data size %zu",
|
|
Packit Service |
310c69 |
savedSize);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
Buffer *buffer;
|
|
Packit Service |
310c69 |
result = makeBuffer(sizeof(*saveData), &buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = readFromBufferedReader(reader, getBufferContents(buffer),
|
|
Packit Service |
310c69 |
bufferLength(buffer));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result, "cannot read index save data");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = resetBufferEnd(buffer, bufferLength(buffer));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = decodeIndexSaveData(buffer, saveData);
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
savedSize -= sizeof(IndexSaveData);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (saveData->version > 1) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_UNSUPPORTED_VERSION,
|
|
Packit Service |
310c69 |
"unkown index save verion number %"
|
|
Packit Service |
310c69 |
PRIu32,
|
|
Packit Service |
310c69 |
saveData->version);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (savedSize > INDEX_STATE_BUFFER_SIZE) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_CORRUPT_COMPONENT,
|
|
Packit Service |
310c69 |
"unexpected index state buffer size %zu",
|
|
Packit Service |
310c69 |
savedSize);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
Buffer *buffer = NULL;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (saveData->version != 0) {
|
|
Packit Service |
310c69 |
result = makeBuffer(INDEX_STATE_BUFFER_SIZE, &buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (savedSize > 0) {
|
|
Packit Service |
310c69 |
result = readFromBufferedReader(reader, getBufferContents(buffer),
|
|
Packit Service |
310c69 |
savedSize);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = resetBufferEnd(buffer, savedSize);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*bufferPtr = buffer;
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct {
|
|
Packit Service |
310c69 |
LayoutRegion *nextRegion;
|
|
Packit Service |
310c69 |
LayoutRegion *lastRegion;
|
|
Packit Service |
310c69 |
uint64_t nextBlock;
|
|
Packit Service |
310c69 |
int result;
|
|
Packit Service |
310c69 |
} RegionIterator;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((format(printf, 2, 3)))
|
|
Packit Service |
310c69 |
static void iterError(RegionIterator *iter, const char *fmt, ...)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
va_list args;
|
|
Packit Service |
310c69 |
va_start(args, fmt);
|
|
Packit Service |
310c69 |
int r = vLogWithStringError(LOG_ERR, UDS_UNEXPECTED_RESULT, fmt, args);
|
|
Packit Service |
310c69 |
va_end(args);
|
|
Packit Service |
310c69 |
if (iter->result == UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
iter->result = r;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Set the next layout region in the layout according to a region table
|
|
Packit Service |
310c69 |
* iterator, unless the iterator already contains an error
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param expect whether to record an error or return false
|
|
Packit Service |
310c69 |
* @param lr the layout region field to set
|
|
Packit Service |
310c69 |
* @param iter the region iterator, which also holds the cumulative
|
|
Packit Service |
310c69 |
* result
|
|
Packit Service |
310c69 |
* @param numBlocks if non-zero, the expected number of blocks
|
|
Packit Service |
310c69 |
* @param kind the expected kind of the region
|
|
Packit Service |
310c69 |
* @param instance the expected instance number of the region
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return true if we meet expectations, false if we do not
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static bool expectLayout(bool expect,
|
|
Packit Service |
310c69 |
LayoutRegion *lr,
|
|
Packit Service |
310c69 |
RegionIterator *iter,
|
|
Packit Service |
310c69 |
uint64_t numBlocks,
|
|
Packit Service |
310c69 |
RegionKind kind,
|
|
Packit Service |
310c69 |
unsigned int instance)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (iter->result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return false;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (iter->nextRegion == iter->lastRegion) {
|
|
Packit Service |
310c69 |
if (expect) {
|
|
Packit Service |
310c69 |
iterError(iter, "ran out of layout regions in region table");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return false;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (iter->nextRegion->startBlock != iter->nextBlock) {
|
|
Packit Service |
310c69 |
iterError(iter, "layout region not at expected offset");
|
|
Packit Service |
310c69 |
return false;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (iter->nextRegion->kind != kind) {
|
|
Packit Service |
310c69 |
if (expect) {
|
|
Packit Service |
310c69 |
iterError(iter, "layout region has incorrect kind");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return false;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (iter->nextRegion->instance != instance) {
|
|
Packit Service |
310c69 |
iterError(iter, "layout region has incorrect instance");
|
|
Packit Service |
310c69 |
return false;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (numBlocks > 0 && iter->nextRegion->numBlocks != numBlocks) {
|
|
Packit Service |
310c69 |
iterError(iter, "layout region size is incorrect");
|
|
Packit Service |
310c69 |
return false;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (lr != NULL) {
|
|
Packit Service |
310c69 |
*lr = *iter->nextRegion;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
iter->nextBlock += iter->nextRegion->numBlocks;
|
|
Packit Service |
310c69 |
iter->nextRegion++;
|
|
Packit Service |
310c69 |
return true;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
static void setupLayout(LayoutRegion *lr,
|
|
Packit Service |
310c69 |
uint64_t *nextAddrPtr,
|
|
Packit Service |
310c69 |
uint64_t regionSize,
|
|
Packit Service |
310c69 |
unsigned int kind,
|
|
Packit Service |
310c69 |
unsigned int instance)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
*lr = (LayoutRegion) {
|
|
Packit Service |
310c69 |
.startBlock = *nextAddrPtr,
|
|
Packit Service |
310c69 |
.numBlocks = regionSize,
|
|
Packit Service |
310c69 |
.checksum = 0,
|
|
Packit Service |
310c69 |
.kind = kind,
|
|
Packit Service |
310c69 |
.instance = instance,
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
*nextAddrPtr += regionSize;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
static void populateIndexSaveLayout(IndexSaveLayout *isl,
|
|
Packit Service |
310c69 |
SuperBlockData *super,
|
|
Packit Service |
310c69 |
unsigned int numZones,
|
|
Packit Service |
310c69 |
IndexSaveType saveType)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
uint64_t nextBlock = isl->indexSave.startBlock;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
setupLayout(&isl->header, &nextBlock, 1, RL_KIND_HEADER, RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
setupLayout(&isl->indexPageMap, &nextBlock, super->pageMapBlocks,
|
|
Packit Service |
310c69 |
RL_KIND_INDEX_PAGE_MAP, RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
uint64_t blocksAvail = (isl->indexSave.numBlocks -
|
|
Packit Service |
310c69 |
(nextBlock - isl->indexSave.startBlock) -
|
|
Packit Service |
310c69 |
super->openChapterBlocks);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (numZones > 0) {
|
|
Packit Service |
310c69 |
uint64_t miBlockCount = blocksAvail / numZones;
|
|
Packit Service |
310c69 |
unsigned int z;
|
|
Packit Service |
310c69 |
for (z = 0; z < numZones; ++z) {
|
|
Packit Service |
310c69 |
LayoutRegion *miz = &isl->masterIndexZones[z];
|
|
Packit Service |
310c69 |
setupLayout(miz, &nextBlock, miBlockCount, RL_KIND_MASTER_INDEX, z);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (saveType == IS_SAVE && isl->openChapter != NULL) {
|
|
Packit Service |
310c69 |
setupLayout(isl->openChapter, &nextBlock, super->openChapterBlocks,
|
|
Packit Service |
310c69 |
RL_KIND_OPEN_CHAPTER, RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
setupLayout(&isl->freeSpace, &nextBlock,
|
|
Packit Service |
310c69 |
(isl->indexSave.numBlocks -
|
|
Packit Service |
310c69 |
(nextBlock - isl->indexSave.startBlock)),
|
|
Packit Service |
310c69 |
RL_KIND_SCRATCH, RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int reconstructIndexSave(IndexSaveLayout *isl,
|
|
Packit Service |
310c69 |
IndexSaveData *saveData,
|
|
Packit Service |
310c69 |
SuperBlockData *super,
|
|
Packit Service |
310c69 |
RegionTable *table)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
isl->numZones = 0;
|
|
Packit Service |
310c69 |
isl->saveData = *saveData;
|
|
Packit Service |
310c69 |
isl->read = false;
|
|
Packit Service |
310c69 |
isl->written = false;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (table->header.type == RH_TYPE_SAVE) {
|
|
Packit Service |
310c69 |
isl->saveType = IS_SAVE;
|
|
Packit Service |
310c69 |
} else if (table->header.type == RH_TYPE_CHECKPOINT) {
|
|
Packit Service |
310c69 |
isl->saveType = IS_CHECKPOINT;
|
|
Packit Service |
310c69 |
} else {
|
|
Packit Service |
310c69 |
isl->saveType = NO_SAVE;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if ((table->header.numRegions == 0) ||
|
|
Packit Service |
310c69 |
((table->header.numRegions == 1) &&
|
|
Packit Service |
310c69 |
(table->regions[0].kind == RL_KIND_SCRATCH)))
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
populateIndexSaveLayout(isl, super, 0, NO_SAVE);
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
RegionIterator iter = {
|
|
Packit Service |
310c69 |
.nextRegion = table->regions,
|
|
Packit Service |
310c69 |
.lastRegion = table->regions + table->header.numRegions,
|
|
Packit Service |
310c69 |
.nextBlock = isl->indexSave.startBlock,
|
|
Packit Service |
310c69 |
.result = UDS_SUCCESS,
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
expectLayout(true, &isl->header, &iter, 1, RL_KIND_HEADER, RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
expectLayout(true, &isl->indexPageMap, &iter, 0,
|
|
Packit Service |
310c69 |
RL_KIND_INDEX_PAGE_MAP, RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
unsigned int n = 0;
|
|
Packit Service |
310c69 |
RegionIterator tmpIter;
|
|
Packit Service |
310c69 |
for (tmpIter = iter;
|
|
Packit Service |
310c69 |
expectLayout(false, NULL, &tmpIter, 0, RL_KIND_MASTER_INDEX, n);
|
|
Packit Service |
310c69 |
++n)
|
|
Packit Service |
310c69 |
;
|
|
Packit Service |
310c69 |
isl->numZones = n;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
int result = UDS_SUCCESS;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (isl->numZones > 0) {
|
|
Packit Service |
310c69 |
result = ALLOCATE(n, LayoutRegion, "master index layout regions",
|
|
Packit Service |
310c69 |
&isl->masterIndexZones);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (isl->saveType == IS_SAVE) {
|
|
Packit Service |
310c69 |
result = ALLOCATE(1, LayoutRegion, "open chapter layout region",
|
|
Packit Service |
310c69 |
&isl->openChapter);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
FREE(isl->masterIndexZones);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
unsigned int z;
|
|
Packit Service |
310c69 |
for (z = 0; z < isl->numZones; ++z) {
|
|
Packit Service |
310c69 |
expectLayout(true, &isl->masterIndexZones[z], &iter, 0,
|
|
Packit Service |
310c69 |
RL_KIND_MASTER_INDEX, z);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (isl->saveType == IS_SAVE) {
|
|
Packit Service |
310c69 |
expectLayout(true, isl->openChapter, &iter, 0,
|
|
Packit Service |
310c69 |
RL_KIND_OPEN_CHAPTER, RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (!expectLayout(false, &isl->freeSpace, &iter, 0,
|
|
Packit Service |
310c69 |
RL_KIND_SCRATCH, RL_SOLE_INSTANCE))
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
isl->freeSpace = (LayoutRegion) {
|
|
Packit Service |
310c69 |
.startBlock = iter.nextBlock,
|
|
Packit Service |
310c69 |
.numBlocks = (isl->indexSave.startBlock +
|
|
Packit Service |
310c69 |
isl->indexSave.numBlocks) - iter.nextBlock,
|
|
Packit Service |
310c69 |
.checksum = 0,
|
|
Packit Service |
310c69 |
.kind = RL_KIND_SCRATCH,
|
|
Packit Service |
310c69 |
.instance = RL_SOLE_INSTANCE,
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
iter.nextBlock = isl->freeSpace.startBlock + isl->freeSpace.numBlocks;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (iter.result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return iter.result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (iter.nextRegion != iter.lastRegion) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_UNEXPECTED_RESULT,
|
|
Packit Service |
310c69 |
"expected %ld additional regions",
|
|
Packit Service |
310c69 |
iter.lastRegion - iter.nextRegion);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (iter.nextBlock != isl->indexSave.startBlock + isl->indexSave.numBlocks) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_UNEXPECTED_RESULT,
|
|
Packit Service |
310c69 |
"index save layout table incomplete");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int loadIndexSave(IndexSaveLayout *isl,
|
|
Packit Service |
310c69 |
SuperBlockData *super,
|
|
Packit Service |
310c69 |
BufferedReader *reader,
|
|
Packit Service |
310c69 |
unsigned int saveId)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
RegionTable *table = NULL;
|
|
Packit Service |
310c69 |
int result = loadRegionTable(reader, &table);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result,
|
|
Packit Service |
310c69 |
"cannot read index 0 save %u header",
|
|
Packit Service |
310c69 |
saveId);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (table->header.regionBlocks != isl->indexSave.numBlocks) {
|
|
Packit Service |
310c69 |
uint64_t regionBlocks = table->header.regionBlocks;
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_CORRUPT_COMPONENT,
|
|
Packit Service |
310c69 |
"unexpected index 0 save %u "
|
|
Packit Service |
310c69 |
"region block count %llu",
|
|
Packit Service |
310c69 |
saveId, regionBlocks);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (table->header.type != RH_TYPE_SAVE &&
|
|
Packit Service |
310c69 |
table->header.type != RH_TYPE_CHECKPOINT &&
|
|
Packit Service |
310c69 |
table->header.type != RH_TYPE_UNSAVED)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
unsigned int type = table->header.type;
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_CORRUPT_COMPONENT, "unexpected"
|
|
Packit Service |
310c69 |
" index 0 save %u header type %u",
|
|
Packit Service |
310c69 |
saveId, type);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
IndexSaveData indexSaveData;
|
|
Packit Service |
310c69 |
result = readIndexSaveData(reader, &indexSaveData, table->header.payload,
|
|
Packit Service |
310c69 |
&isl->indexStateBuffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result,
|
|
Packit Service |
310c69 |
"unknown index 0 save %u data format",
|
|
Packit Service |
310c69 |
saveId);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = reconstructIndexSave(isl, &indexSaveData, super, table);
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBuffer(&isl->indexStateBuffer);
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result,
|
|
Packit Service |
310c69 |
"cannot reconstruct index 0 save %u",
|
|
Packit Service |
310c69 |
saveId);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
isl->read = true;
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int loadSubIndexRegions(IndexLayout *layout)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
unsigned int j;
|
|
Packit Service |
310c69 |
for (j = 0; j < layout->super.maxSaves; ++j) {
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl = &layout->index.saves[j];
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
BufferedReader *reader;
|
|
Packit Service |
310c69 |
int result = openLayoutReader(layout, &isl->indexSave, &reader);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
logErrorWithStringError(result, "cannot get reader for index 0 save %u",
|
|
Packit Service |
310c69 |
j);
|
|
Packit Service |
310c69 |
while (j-- > 0) {
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl = &layout->index.saves[j];
|
|
Packit Service |
310c69 |
FREE(isl->masterIndexZones);
|
|
Packit Service |
310c69 |
FREE(isl->openChapter);
|
|
Packit Service |
310c69 |
freeBuffer(&isl->indexStateBuffer);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = loadIndexSave(isl, &layout->super, reader, j);
|
|
Packit Service |
310c69 |
freeBufferedReader(reader);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
while (j-- > 0) {
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl = &layout->index.saves[j];
|
|
Packit Service |
310c69 |
FREE(isl->masterIndexZones);
|
|
Packit Service |
310c69 |
FREE(isl->openChapter);
|
|
Packit Service |
310c69 |
freeBuffer(&isl->indexStateBuffer);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
static int loadIndexLayout(IndexLayout *layout)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
BufferedReader *reader;
|
|
Packit Service |
310c69 |
int result = openBufferedReader(layout->factory, layout->offset,
|
|
Packit Service |
310c69 |
UDS_BLOCK_SIZE, &reader);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result, "unable to read superblock");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = loadSuperBlock(layout, UDS_BLOCK_SIZE,
|
|
Packit Service |
310c69 |
layout->offset / UDS_BLOCK_SIZE, reader);
|
|
Packit Service |
310c69 |
freeBufferedReader(reader);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
FREE(layout->index.saves);
|
|
Packit Service |
310c69 |
layout->index.saves = NULL;
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = loadSubIndexRegions(layout);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
FREE(layout->index.saves);
|
|
Packit Service |
310c69 |
layout->index.saves = NULL;
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
static void generateSuperBlockData(size_t blockSize,
|
|
Packit Service |
310c69 |
unsigned int maxSaves,
|
|
Packit Service |
310c69 |
uint64_t openChapterBlocks,
|
|
Packit Service |
310c69 |
uint64_t pageMapBlocks,
|
|
Packit Service |
310c69 |
SuperBlockData *super)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
memset(super, 0, sizeof(*super));
|
|
Packit Service |
310c69 |
memcpy(super->magicLabel, SINGLE_FILE_MAGIC_1, SINGLE_FILE_MAGIC_1_LENGTH);
|
|
Packit Service |
310c69 |
createUniqueNonceData(super->nonceInfo, sizeof(super->nonceInfo));
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
super->nonce = generateMasterNonce(super->nonceInfo,
|
|
Packit Service |
310c69 |
sizeof(super->nonceInfo));
|
|
Packit Service |
310c69 |
super->version = SUPER_VERSION_CURRENT;
|
|
Packit Service |
310c69 |
super->blockSize = blockSize;
|
|
Packit Service |
310c69 |
super->numIndexes = 1;
|
|
Packit Service |
310c69 |
super->maxSaves = maxSaves;
|
|
Packit Service |
310c69 |
super->openChapterBlocks = openChapterBlocks;
|
|
Packit Service |
310c69 |
super->pageMapBlocks = pageMapBlocks;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int resetIndexSaveLayout(IndexSaveLayout *isl,
|
|
Packit Service |
310c69 |
uint64_t *nextBlockPtr,
|
|
Packit Service |
310c69 |
uint64_t saveBlocks,
|
|
Packit Service |
310c69 |
uint64_t pageMapBlocks,
|
|
Packit Service |
310c69 |
unsigned int instance)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
uint64_t startBlock = *nextBlockPtr;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (isl->masterIndexZones) {
|
|
Packit Service |
310c69 |
FREE(isl->masterIndexZones);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (isl->openChapter) {
|
|
Packit Service |
310c69 |
FREE(isl->openChapter);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (isl->indexStateBuffer) {
|
|
Packit Service |
310c69 |
freeBuffer(&isl->indexStateBuffer);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
memset(isl, 0, sizeof(*isl));
|
|
Packit Service |
310c69 |
isl->saveType = NO_SAVE;
|
|
Packit Service |
310c69 |
setupLayout(&isl->indexSave, &startBlock, saveBlocks, RL_KIND_SAVE,
|
|
Packit Service |
310c69 |
instance);
|
|
Packit Service |
310c69 |
setupLayout(&isl->header, nextBlockPtr, 1, RL_KIND_HEADER,
|
|
Packit Service |
310c69 |
RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
setupLayout(&isl->indexPageMap, nextBlockPtr, pageMapBlocks,
|
|
Packit Service |
310c69 |
RL_KIND_INDEX_PAGE_MAP, RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
uint64_t remaining = startBlock - *nextBlockPtr;
|
|
Packit Service |
310c69 |
setupLayout(&isl->freeSpace, nextBlockPtr, remaining, RL_KIND_SCRATCH,
|
|
Packit Service |
310c69 |
RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
// number of zones is a save-time parameter
|
|
Packit Service |
310c69 |
// presence of open chapter is a save-time parameter
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
static void defineSubIndexNonce(SubIndexLayout *sil,
|
|
Packit Service |
310c69 |
uint64_t masterNonce,
|
|
Packit Service |
310c69 |
unsigned int indexId)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
struct subIndexNonceData {
|
|
Packit Service |
310c69 |
uint64_t offset;
|
|
Packit Service |
310c69 |
uint16_t indexId;
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
byte buffer[sizeof(struct subIndexNonceData)] = { 0 };
|
|
Packit Service |
310c69 |
size_t offset = 0;
|
|
Packit Service |
310c69 |
encodeUInt64LE(buffer, &offset, sil->subIndex.startBlock);
|
|
Packit Service |
310c69 |
encodeUInt16LE(buffer, &offset, indexId);
|
|
Packit Service |
310c69 |
sil->nonce = generateSecondaryNonce(masterNonce, buffer, sizeof(buffer));
|
|
Packit Service |
310c69 |
if (sil->nonce == 0) {
|
|
Packit Service |
310c69 |
sil->nonce = generateSecondaryNonce(~masterNonce + 1,
|
|
Packit Service |
310c69 |
buffer, sizeof(buffer));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int setupSubIndex(SubIndexLayout *sil,
|
|
Packit Service |
310c69 |
uint64_t *nextBlockPtr,
|
|
Packit Service |
310c69 |
SaveLayoutSizes *sls,
|
|
Packit Service |
310c69 |
unsigned int instance,
|
|
Packit Service |
310c69 |
uint64_t masterNonce)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
uint64_t startBlock = *nextBlockPtr;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
setupLayout(&sil->subIndex, &startBlock, sls->subIndexBlocks,
|
|
Packit Service |
310c69 |
RL_KIND_INDEX, instance);
|
|
Packit Service |
310c69 |
setupLayout(&sil->volume, nextBlockPtr, sls->volumeBlocks,
|
|
Packit Service |
310c69 |
RL_KIND_VOLUME, RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
unsigned int i;
|
|
Packit Service |
310c69 |
for (i = 0; i < sls->numSaves; ++i) {
|
|
Packit Service |
310c69 |
int result = resetIndexSaveLayout(&sil->saves[i], nextBlockPtr,
|
|
Packit Service |
310c69 |
sls->saveBlocks, sls->pageMapBlocks, i);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (startBlock != *nextBlockPtr) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_UNEXPECTED_RESULT,
|
|
Packit Service |
310c69 |
"sub index layout regions don't agree");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
defineSubIndexNonce(sil, masterNonce, instance);
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Initialize a single file layout using the save layout sizes specified.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param layout the layout to initialize
|
|
Packit Service |
310c69 |
* @param offset the offset in bytes from the start of the backing storage
|
|
Packit Service |
310c69 |
* @param size the size in bytes of the backing storage
|
|
Packit Service |
310c69 |
* @param sls a populated SaveLayoutSizes object
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code, potentially
|
|
Packit Service |
310c69 |
* UDS_INSUFFICIENT_INDEX_SPACE if the size of the backing store
|
|
Packit Service |
310c69 |
* is not sufficient for the index configuration,
|
|
Packit Service |
310c69 |
* UDS_BAD_INDEX_ALIGNMENT if the offset specified does not
|
|
Packit Service |
310c69 |
* align properly with the index block and page sizes]
|
|
Packit Service |
310c69 |
* various other errors
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int initSingleFileLayout(IndexLayout *layout,
|
|
Packit Service |
310c69 |
uint64_t offset,
|
|
Packit Service |
310c69 |
uint64_t size,
|
|
Packit Service |
310c69 |
SaveLayoutSizes *sls)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
layout->totalBlocks = sls->totalBlocks;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (size < sls->totalBlocks * sls->blockSize) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_INSUFFICIENT_INDEX_SPACE,
|
|
Packit Service |
310c69 |
"not enough space for index as configured");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
generateSuperBlockData(sls->blockSize, sls->numSaves, sls->openChapterBlocks,
|
|
Packit Service |
310c69 |
sls->pageMapBlocks, &layout->super);
|
|
Packit Service |
310c69 |
initializeIndexVersion(&layout->indexVersion, SUPER_VERSION_CURRENT);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
int result = allocateSingleFileParts(layout, &layout->super);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
uint64_t nextBlock = offset / sls->blockSize;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
setupLayout(&layout->header, &nextBlock, 1, RL_KIND_HEADER,
|
|
Packit Service |
310c69 |
RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
setupLayout(&layout->config, &nextBlock, 1, RL_KIND_CONFIG,
|
|
Packit Service |
310c69 |
RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
result = setupSubIndex(&layout->index, &nextBlock, sls, 0,
|
|
Packit Service |
310c69 |
layout->super.nonce);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
setupLayout(&layout->seal, &nextBlock, 1, RL_KIND_SEAL, RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
if (nextBlock * sls->blockSize > offset + size) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_UNEXPECTED_RESULT,
|
|
Packit Service |
310c69 |
"layout does not fit as expected");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
static void expectSubIndex(SubIndexLayout *sil,
|
|
Packit Service |
310c69 |
RegionIterator *iter,
|
|
Packit Service |
310c69 |
SuperBlockData *super,
|
|
Packit Service |
310c69 |
unsigned int instance)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (iter->result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
uint64_t startBlock = iter->nextBlock;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
expectLayout(true, &sil->subIndex, iter, 0, RL_KIND_INDEX, instance);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
uint64_t endBlock = iter->nextBlock;
|
|
Packit Service |
310c69 |
iter->nextBlock = startBlock;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
expectLayout(true, &sil->volume, iter, 0, RL_KIND_VOLUME, RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
unsigned int i;
|
|
Packit Service |
310c69 |
for (i = 0; i < super->maxSaves; ++i) {
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl = &sil->saves[i];
|
|
Packit Service |
310c69 |
expectLayout(true, &isl->indexSave, iter, 0, RL_KIND_SAVE, i);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (iter->nextBlock != endBlock) {
|
|
Packit Service |
310c69 |
iterError(iter, "sub index region does not span all saves");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
defineSubIndexNonce(sil, super->nonce, instance);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Initialize a single file layout from the region table and super block data
|
|
Packit Service |
310c69 |
* stored in stable storage.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param layout the layout to initialize
|
|
Packit Service |
310c69 |
* @param region the IO region for this layout
|
|
Packit Service |
310c69 |
* @param super the super block data read from the superblock
|
|
Packit Service |
310c69 |
* @param table the region table read from the superblock
|
|
Packit Service |
310c69 |
* @param firstBlock the first block number in the region
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int reconstituteSingleFileLayout(IndexLayout *layout,
|
|
Packit Service |
310c69 |
SuperBlockData *super,
|
|
Packit Service |
310c69 |
RegionTable *table,
|
|
Packit Service |
310c69 |
uint64_t firstBlock)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
layout->super = *super;
|
|
Packit Service |
310c69 |
layout->totalBlocks = table->header.regionBlocks;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
RegionIterator iter = {
|
|
Packit Service |
310c69 |
.nextRegion = table->regions,
|
|
Packit Service |
310c69 |
.lastRegion = table->regions + table->header.numRegions,
|
|
Packit Service |
310c69 |
.nextBlock = firstBlock,
|
|
Packit Service |
310c69 |
.result = UDS_SUCCESS
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
expectLayout(true, &layout->header, &iter, 1, RL_KIND_HEADER,
|
|
Packit Service |
310c69 |
RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
expectLayout(true, &layout->config, &iter, 1, RL_KIND_CONFIG,
|
|
Packit Service |
310c69 |
RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
expectSubIndex(&layout->index, &iter, &layout->super, 0);
|
|
Packit Service |
310c69 |
expectLayout(true, &layout->seal, &iter, 1, RL_KIND_SEAL, RL_SOLE_INSTANCE);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (iter.result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return iter.result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (iter.nextBlock != firstBlock + layout->totalBlocks) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_UNEXPECTED_RESULT,
|
|
Packit Service |
310c69 |
"layout table does not span total blocks");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int saveSubIndexRegions(IndexLayout *layout)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
SubIndexLayout *sil = &layout->index;
|
|
Packit Service |
310c69 |
unsigned int j;
|
|
Packit Service |
310c69 |
for (j = 0; j < layout->super.maxSaves; ++j) {
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl = &sil->saves[j];
|
|
Packit Service |
310c69 |
int result = writeIndexSaveLayout(layout, isl);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result,
|
|
Packit Service |
310c69 |
"unable to format index %u save 0 layout",
|
|
Packit Service |
310c69 |
j);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int makeSingleFileRegionTable(IndexLayout *layout,
|
|
Packit Service |
310c69 |
unsigned int *numRegionsPtr,
|
|
Packit Service |
310c69 |
RegionTable **tablePtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
unsigned int numRegions =
|
|
Packit Service |
310c69 |
1 + // header
|
|
Packit Service |
310c69 |
1 + // config
|
|
Packit Service |
310c69 |
1 + // index
|
|
Packit Service |
310c69 |
1 + // volume
|
|
Packit Service |
310c69 |
layout->super.maxSaves + // saves
|
|
Packit Service |
310c69 |
1; // seal
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
RegionTable *table;
|
|
Packit Service |
310c69 |
int result = ALLOCATE_EXTENDED(RegionTable, numRegions, LayoutRegion,
|
|
Packit Service |
310c69 |
"layout region table", &table);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
LayoutRegion *lr = &table->regions[0];
|
|
Packit Service |
310c69 |
*lr++ = layout->header;
|
|
Packit Service |
310c69 |
*lr++ = layout->config;
|
|
Packit Service |
310c69 |
SubIndexLayout *sil = &layout->index;
|
|
Packit Service |
310c69 |
*lr++ = sil->subIndex;
|
|
Packit Service |
310c69 |
*lr++ = sil->volume;
|
|
Packit Service |
310c69 |
unsigned int j;
|
|
Packit Service |
310c69 |
for (j = 0; j < layout->super.maxSaves; ++j) {
|
|
Packit Service |
310c69 |
*lr++ = sil->saves[j].indexSave;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
*lr++ = layout->seal;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = ASSERT((lr == &table->regions[numRegions]),
|
|
Packit Service |
310c69 |
"incorrect number of regions");
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*numRegionsPtr = numRegions;
|
|
Packit Service |
310c69 |
*tablePtr = table;
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int encodeIndexSaveData(Buffer *buffer, IndexSaveData *saveData)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = putUInt64LEIntoBuffer(buffer, saveData->timestamp);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt64LEIntoBuffer(buffer, saveData->nonce);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt32LEIntoBuffer(buffer, saveData->version);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = zeroBytes(buffer, 4); /* padding */
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = ASSERT_LOG_ONLY(contentLength(buffer) == sizeof *saveData,
|
|
Packit Service |
310c69 |
"%zu bytes encoded of %zu expected",
|
|
Packit Service |
310c69 |
contentLength(buffer), sizeof(*saveData));
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int encodeRegionHeader(Buffer *buffer, RegionHeader *header)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
size_t startingLength = contentLength(buffer);
|
|
Packit Service |
310c69 |
int result = putUInt64LEIntoBuffer(buffer, REGION_MAGIC);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt64LEIntoBuffer(buffer, header->regionBlocks);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt16LEIntoBuffer(buffer, header->type);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt16LEIntoBuffer(buffer, header->version);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt16LEIntoBuffer(buffer, header->numRegions);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt16LEIntoBuffer(buffer, header->payload);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result
|
|
Packit Service |
310c69 |
= ASSERT_LOG_ONLY(contentLength(buffer) - startingLength == sizeof(*header),
|
|
Packit Service |
310c69 |
"%zu bytes encoded, of %zu expected",
|
|
Packit Service |
310c69 |
contentLength(buffer) - startingLength, sizeof(*header));
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int encodeLayoutRegion(Buffer *buffer, LayoutRegion *region)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
size_t startingLength = contentLength(buffer);
|
|
Packit Service |
310c69 |
int result = putUInt64LEIntoBuffer(buffer, region->startBlock);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt64LEIntoBuffer(buffer, region->numBlocks);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt32LEIntoBuffer(buffer, region->checksum);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt16LEIntoBuffer(buffer, region->kind);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt16LEIntoBuffer(buffer, region->instance);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result
|
|
Packit Service |
310c69 |
= ASSERT_LOG_ONLY(contentLength(buffer) - startingLength == sizeof(*region),
|
|
Packit Service |
310c69 |
"%zu bytes encoded, of %zu expected",
|
|
Packit Service |
310c69 |
contentLength(buffer) - startingLength, sizeof(*region));
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int encodeSuperBlockData(Buffer *buffer, SuperBlockData *super)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = putBytes(buffer, 32, &super->magicLabel);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putBytes(buffer, 32, &super->nonceInfo);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt64LEIntoBuffer(buffer, super->nonce);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt32LEIntoBuffer(buffer, super->version);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt32LEIntoBuffer(buffer, super->blockSize);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt16LEIntoBuffer(buffer, super->numIndexes);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt16LEIntoBuffer(buffer, super->maxSaves);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = zeroBytes(buffer, 4); // aligment
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt64LEIntoBuffer(buffer, super->openChapterBlocks);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = putUInt64LEIntoBuffer(buffer, super->pageMapBlocks);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = ASSERT_LOG_ONLY(contentLength(buffer) == sizeof(SuperBlockData),
|
|
Packit Service |
310c69 |
"%zu bytes encoded, of %zu expected",
|
|
Packit Service |
310c69 |
contentLength(buffer), sizeof(SuperBlockData));
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int writeSingleFileHeader(IndexLayout *layout,
|
|
Packit Service |
310c69 |
RegionTable *table,
|
|
Packit Service |
310c69 |
unsigned int numRegions,
|
|
Packit Service |
310c69 |
BufferedWriter *writer)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
table->header = (RegionHeader) {
|
|
Packit Service |
310c69 |
.magic = REGION_MAGIC,
|
|
Packit Service |
310c69 |
.regionBlocks = layout->totalBlocks,
|
|
Packit Service |
310c69 |
.type = RH_TYPE_SUPER,
|
|
Packit Service |
310c69 |
.version = 1,
|
|
Packit Service |
310c69 |
.numRegions = numRegions,
|
|
Packit Service |
310c69 |
.payload = sizeof(layout->super),
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
size_t tableSize = sizeof(RegionTable) + numRegions * sizeof(LayoutRegion);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
Buffer *buffer;
|
|
Packit Service |
310c69 |
int result = makeBuffer(tableSize, &buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = encodeRegionHeader(buffer, &table->header);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
unsigned int i;
|
|
Packit Service |
310c69 |
for (i = 0; i < numRegions; i++) {
|
|
Packit Service |
310c69 |
if (result == UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
result = encodeLayoutRegion(buffer, &table->regions[i]);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (result == UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
result = writeToBufferedWriter(writer, getBufferContents(buffer),
|
|
Packit Service |
310c69 |
contentLength(buffer));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = makeBuffer(sizeof(layout->super), &buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = encodeSuperBlockData(buffer, &layout->super);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = writeToBufferedWriter(writer, getBufferContents(buffer),
|
|
Packit Service |
310c69 |
contentLength(buffer));
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return flushBufferedWriter(writer);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int saveSingleFileConfiguration(IndexLayout *layout)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = saveSubIndexRegions(layout);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
RegionTable *table;
|
|
Packit Service |
310c69 |
unsigned int numRegions;
|
|
Packit Service |
310c69 |
result = makeSingleFileRegionTable(layout, &numRegions, &table);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
BufferedWriter *writer = NULL;
|
|
Packit Service |
310c69 |
result = openLayoutWriter(layout, &layout->header, &writer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = writeSingleFileHeader(layout, table, numRegions, writer);
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
freeBufferedWriter(writer);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
void putIndexLayout(IndexLayout **layoutPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (layoutPtr == NULL) {
|
|
Packit Service |
310c69 |
return;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
IndexLayout *layout = *layoutPtr;
|
|
Packit Service |
310c69 |
*layoutPtr = NULL;
|
|
Packit Service |
310c69 |
if ((layout == NULL) || (--layout->refCount > 0)) {
|
|
Packit Service |
310c69 |
return;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
SubIndexLayout *sil = &layout->index;
|
|
Packit Service |
310c69 |
if (sil->saves != NULL) {
|
|
Packit Service |
310c69 |
unsigned int j;
|
|
Packit Service |
310c69 |
for (j = 0; j < layout->super.maxSaves; ++j) {
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl = &sil->saves[j];
|
|
Packit Service |
310c69 |
FREE(isl->masterIndexZones);
|
|
Packit Service |
310c69 |
FREE(isl->openChapter);
|
|
Packit Service |
310c69 |
freeBuffer(&isl->indexStateBuffer);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
FREE(sil->saves);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (layout->factory != NULL) {
|
|
Packit Service |
310c69 |
putIOFactory(layout->factory);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
FREE(layout);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
void getIndexLayout(IndexLayout *layout, IndexLayout **layoutPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
++layout->refCount;
|
|
Packit Service |
310c69 |
*layoutPtr = layout;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
const struct index_version *getIndexVersion(IndexLayout *layout)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return &layout->indexVersion;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int writeIndexConfig(IndexLayout *layout, UdsConfiguration config)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
BufferedWriter *writer = NULL;
|
|
Packit Service |
310c69 |
int result = openLayoutWriter(layout, &layout->config, &writer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result, "failed to open config region");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = writeConfigContents(writer, config);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBufferedWriter(writer);
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result, "failed to write config region");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = flushBufferedWriter(writer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBufferedWriter(writer);
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result, "cannot flush config writer");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
freeBufferedWriter(writer);
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int verifyIndexConfig(IndexLayout *layout, UdsConfiguration config)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
BufferedReader *reader = NULL;
|
|
Packit Service |
310c69 |
int result = openLayoutReader(layout, &layout->config, &reader);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result, "failed to open config reader");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
struct udsConfiguration storedConfig;
|
|
Packit Service |
310c69 |
result = readConfigContents(reader, &storedConfig);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBufferedReader(reader);
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result, "failed to read config region");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
freeBufferedReader(reader);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return (areUdsConfigurationsEqual(&storedConfig, config)
|
|
Packit Service |
310c69 |
? UDS_SUCCESS
|
|
Packit Service |
310c69 |
: UDS_NO_INDEX);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#ifdef __KERNEL__
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int openVolumeBufio(IndexLayout *layout,
|
|
Packit Service |
310c69 |
size_t blockSize,
|
|
Packit Service |
310c69 |
unsigned int reservedBuffers,
|
|
Packit Service |
310c69 |
struct dm_bufio_client **clientPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
off_t offset = layout->index.volume.startBlock * layout->super.blockSize;
|
|
Packit Service |
310c69 |
return makeBufio(layout->factory, offset, blockSize, reservedBuffers,
|
|
Packit Service |
310c69 |
clientPtr);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
#else
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int openVolumeRegion(IndexLayout *layout, IORegion **regionPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
LayoutRegion *lr = &layout->index.volume;
|
|
Packit Service |
310c69 |
off_t start = lr->startBlock * layout->super.blockSize;
|
|
Packit Service |
310c69 |
size_t size = lr->numBlocks * layout->super.blockSize;
|
|
Packit Service |
310c69 |
int result = makeIORegion(layout->factory, start, size, regionPtr);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(result,
|
|
Packit Service |
310c69 |
"cannot access index volume region");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
#endif
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
uint64_t getVolumeNonce(IndexLayout *layout)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return layout->index.nonce;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
static uint64_t generateIndexSaveNonce(uint64_t volumeNonce,
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
struct SaveNonceData {
|
|
Packit Service |
310c69 |
IndexSaveData data;
|
|
Packit Service |
310c69 |
uint64_t offset;
|
|
Packit Service |
310c69 |
} nonceData;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
nonceData.data = isl->saveData;
|
|
Packit Service |
310c69 |
nonceData.data.nonce = 0;
|
|
Packit Service |
310c69 |
nonceData.offset = isl->indexSave.startBlock;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
byte buffer[sizeof(nonceData)];
|
|
Packit Service |
310c69 |
size_t offset = 0;
|
|
Packit Service |
310c69 |
encodeUInt64LE(buffer, &offset, nonceData.data.timestamp);
|
|
Packit Service |
310c69 |
encodeUInt64LE(buffer, &offset, nonceData.data.nonce);
|
|
Packit Service |
310c69 |
encodeUInt32LE(buffer, &offset, nonceData.data.version);
|
|
Packit Service |
310c69 |
encodeUInt32LE(buffer, &offset, 0U); // padding
|
|
Packit Service |
310c69 |
encodeUInt64LE(buffer, &offset, nonceData.offset);
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY(offset == sizeof(nonceData),
|
|
Packit Service |
310c69 |
"%zu bytes encoded of %zu expected",
|
|
Packit Service |
310c69 |
offset, sizeof(nonceData));
|
|
Packit Service |
310c69 |
return generateSecondaryNonce(volumeNonce, buffer, sizeof(buffer));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
static int validateIndexSaveLayout(IndexSaveLayout *isl,
|
|
Packit Service |
310c69 |
uint64_t volumeNonce,
|
|
Packit Service |
310c69 |
uint64_t *saveTimePtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (isl->saveType == NO_SAVE || isl->numZones == 0 ||
|
|
Packit Service |
310c69 |
isl->saveData.timestamp == 0)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return UDS_BAD_STATE;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (isl->saveData.nonce != generateIndexSaveNonce(volumeNonce, isl)) {
|
|
Packit Service |
310c69 |
return UDS_BAD_STATE;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (saveTimePtr != NULL) {
|
|
Packit Service |
310c69 |
*saveTimePtr = isl->saveData.timestamp;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int selectOldestIndexSaveLayout(SubIndexLayout *sil,
|
|
Packit Service |
310c69 |
unsigned int maxSaves,
|
|
Packit Service |
310c69 |
IndexSaveLayout **islPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
IndexSaveLayout *oldest = NULL;
|
|
Packit Service |
310c69 |
uint64_t oldestTime = 0;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// find the oldest valid or first invalid slot
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl;
|
|
Packit Service |
310c69 |
for (isl = sil->saves; isl < sil->saves + maxSaves; ++isl) {
|
|
Packit Service |
310c69 |
uint64_t saveTime = 0;
|
|
Packit Service |
310c69 |
int result = validateIndexSaveLayout(isl, sil->nonce, &saveTime);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
saveTime = 0;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (oldest == NULL || saveTime < oldestTime) {
|
|
Packit Service |
310c69 |
oldest = isl;
|
|
Packit Service |
310c69 |
oldestTime = saveTime;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
int result = ASSERT((oldest != NULL), "no oldest or free save slot");
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
*islPtr = oldest;
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int selectLatestIndexSaveLayout(SubIndexLayout *sil,
|
|
Packit Service |
310c69 |
unsigned int maxSaves,
|
|
Packit Service |
310c69 |
IndexSaveLayout **islPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
IndexSaveLayout *latest = NULL;
|
|
Packit Service |
310c69 |
uint64_t latestTime = 0;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// find the latest valid save slot
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl;
|
|
Packit Service |
310c69 |
for (isl = sil->saves; isl < sil->saves + maxSaves; ++isl) {
|
|
Packit Service |
310c69 |
uint64_t saveTime = 0;
|
|
Packit Service |
310c69 |
int result = validateIndexSaveLayout(isl, sil->nonce, &saveTime);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
continue;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (saveTime > latestTime) {
|
|
Packit Service |
310c69 |
latest = isl;
|
|
Packit Service |
310c69 |
latestTime = saveTime;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (latest == NULL) {
|
|
Packit Service |
310c69 |
return UDS_INDEX_NOT_SAVED_CLEANLY;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
*islPtr = latest;
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
static uint64_t getTimeMS(AbsTime time)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
time_t t = asTimeT(time);
|
|
Packit Service |
310c69 |
RelTime r = timeDifference(time, fromTimeT(t));
|
|
Packit Service |
310c69 |
return (uint64_t) t * 1000 + relTimeToMilliseconds(r);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int instantiateIndexSaveLayout(IndexSaveLayout *isl,
|
|
Packit Service |
310c69 |
SuperBlockData *super,
|
|
Packit Service |
310c69 |
uint64_t volumeNonce,
|
|
Packit Service |
310c69 |
unsigned int numZones,
|
|
Packit Service |
310c69 |
IndexSaveType saveType)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = UDS_SUCCESS;
|
|
Packit Service |
310c69 |
if (isl->openChapter && saveType == IS_CHECKPOINT) {
|
|
Packit Service |
310c69 |
FREE(isl->openChapter);
|
|
Packit Service |
310c69 |
isl->openChapter = NULL;
|
|
Packit Service |
310c69 |
} else if (isl->openChapter == NULL && saveType == IS_SAVE) {
|
|
Packit Service |
310c69 |
result = ALLOCATE(1, LayoutRegion, "open chapter layout",
|
|
Packit Service |
310c69 |
&isl->openChapter);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (numZones != isl->numZones) {
|
|
Packit Service |
310c69 |
if (isl->masterIndexZones != NULL) {
|
|
Packit Service |
310c69 |
FREE(isl->masterIndexZones);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = ALLOCATE(numZones, LayoutRegion, "master index zone layouts",
|
|
Packit Service |
310c69 |
&isl->masterIndexZones);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
isl->numZones = numZones;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
populateIndexSaveLayout(isl, super, numZones, saveType);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = makeBuffer(INDEX_STATE_BUFFER_SIZE, &isl->indexStateBuffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
isl->read = isl->written = false;
|
|
Packit Service |
310c69 |
isl->saveType = saveType;
|
|
Packit Service |
310c69 |
memset(&isl->saveData, 0, sizeof(isl->saveData));
|
|
Packit Service |
310c69 |
isl->saveData.timestamp = getTimeMS(currentTime(CLOCK_REALTIME));
|
|
Packit Service |
310c69 |
isl->saveData.version = 1;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
isl->saveData.nonce = generateIndexSaveNonce(volumeNonce, isl);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int invalidateOldSave(IndexLayout *layout, IndexSaveLayout *isl)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
uint64_t startBlock = isl->indexSave.startBlock;
|
|
Packit Service |
310c69 |
uint64_t saveBlocks = isl->indexSave.numBlocks;
|
|
Packit Service |
310c69 |
unsigned int save = isl->indexSave.instance;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
int result = resetIndexSaveLayout(isl, &startBlock, saveBlocks,
|
|
Packit Service |
310c69 |
layout->super.pageMapBlocks, save);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return writeIndexSaveLayout(layout, isl);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int setupIndexSaveSlot(IndexLayout *layout,
|
|
Packit Service |
310c69 |
unsigned int numZones,
|
|
Packit Service |
310c69 |
IndexSaveType saveType,
|
|
Packit Service |
310c69 |
unsigned int *saveSlotPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
SubIndexLayout *sil = &layout->index;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl = NULL;
|
|
Packit Service |
310c69 |
int result = selectOldestIndexSaveLayout(sil, layout->super.maxSaves, &isl;;
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = invalidateOldSave(layout, isl);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = instantiateIndexSaveLayout(isl, &layout->super, sil->nonce,
|
|
Packit Service |
310c69 |
numZones, saveType);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*saveSlotPtr = isl - sil->saves;
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int findLatestIndexSaveSlot(IndexLayout *layout,
|
|
Packit Service |
310c69 |
unsigned int *numZonesPtr,
|
|
Packit Service |
310c69 |
unsigned int *slotPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
SubIndexLayout *sil = &layout->index;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl = NULL;
|
|
Packit Service |
310c69 |
int result = selectLatestIndexSaveLayout(sil, layout->super.maxSaves, &isl;;
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (numZonesPtr != NULL) {
|
|
Packit Service |
310c69 |
*numZonesPtr = isl->numZones;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (slotPtr != NULL) {
|
|
Packit Service |
310c69 |
*slotPtr = isl - sil->saves;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int makeIndexSaveRegionTable(IndexSaveLayout *isl,
|
|
Packit Service |
310c69 |
unsigned int *numRegionsPtr,
|
|
Packit Service |
310c69 |
RegionTable **tablePtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
unsigned int numRegions =
|
|
Packit Service |
310c69 |
1 + // header
|
|
Packit Service |
310c69 |
1 + // index page map
|
|
Packit Service |
310c69 |
isl->numZones + // master index zones
|
|
Packit Service |
310c69 |
(bool) isl->openChapter; // open chapter if needed
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (isl->freeSpace.numBlocks > 0) {
|
|
Packit Service |
310c69 |
numRegions++;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
RegionTable *table;
|
|
Packit Service |
310c69 |
int result = ALLOCATE_EXTENDED(RegionTable, numRegions, LayoutRegion,
|
|
Packit Service |
310c69 |
"layout region table for ISL", &table);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
LayoutRegion *lr = &table->regions[0];
|
|
Packit Service |
310c69 |
*lr++ = isl->header;
|
|
Packit Service |
310c69 |
*lr++ = isl->indexPageMap;
|
|
Packit Service |
310c69 |
unsigned int z;
|
|
Packit Service |
310c69 |
for (z = 0; z < isl->numZones; ++z) {
|
|
Packit Service |
310c69 |
*lr++ = isl->masterIndexZones[z];
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (isl->openChapter) {
|
|
Packit Service |
310c69 |
*lr++ = *isl->openChapter;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (isl->freeSpace.numBlocks > 0) {
|
|
Packit Service |
310c69 |
*lr++ = isl->freeSpace;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = ASSERT((lr == &table->regions[numRegions]),
|
|
Packit Service |
310c69 |
"incorrect number of ISL regions");
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*numRegionsPtr = numRegions;
|
|
Packit Service |
310c69 |
*tablePtr = table;
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
static unsigned int regionTypeForSaveType(IndexSaveType saveType)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
switch (saveType) {
|
|
Packit Service |
310c69 |
case IS_SAVE:
|
|
Packit Service |
310c69 |
return RH_TYPE_SAVE;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
case IS_CHECKPOINT:
|
|
Packit Service |
310c69 |
return RH_TYPE_CHECKPOINT;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
default:
|
|
Packit Service |
310c69 |
break;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return RH_TYPE_UNSAVED;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int writeIndexSaveHeader(IndexSaveLayout *isl,
|
|
Packit Service |
310c69 |
RegionTable *table,
|
|
Packit Service |
310c69 |
unsigned int numRegions,
|
|
Packit Service |
310c69 |
BufferedWriter *writer)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
size_t payload = sizeof(isl->saveData);
|
|
Packit Service |
310c69 |
if (isl->indexStateBuffer != NULL) {
|
|
Packit Service |
310c69 |
payload += contentLength(isl->indexStateBuffer);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
table->header = (RegionHeader) {
|
|
Packit Service |
310c69 |
.magic = REGION_MAGIC,
|
|
Packit Service |
310c69 |
.regionBlocks = isl->indexSave.numBlocks,
|
|
Packit Service |
310c69 |
.type = regionTypeForSaveType(isl->saveType),
|
|
Packit Service |
310c69 |
.version = 1,
|
|
Packit Service |
310c69 |
.numRegions = numRegions,
|
|
Packit Service |
310c69 |
.payload = payload,
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
size_t tableSize = sizeof(RegionTable) + numRegions * sizeof(LayoutRegion);
|
|
Packit Service |
310c69 |
Buffer *buffer;
|
|
Packit Service |
310c69 |
int result = makeBuffer(tableSize, &buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = encodeRegionHeader(buffer, &table->header);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
unsigned int i;
|
|
Packit Service |
310c69 |
for (i = 0; i < numRegions; i++) {
|
|
Packit Service |
310c69 |
result = encodeLayoutRegion(buffer, &table->regions[i]);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = ASSERT_LOG_ONLY(contentLength(buffer) == tableSize,
|
|
Packit Service |
310c69 |
"%zu bytes encoded of %zu expected",
|
|
Packit Service |
310c69 |
contentLength(buffer), tableSize);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = writeToBufferedWriter(writer, getBufferContents(buffer),
|
|
Packit Service |
310c69 |
contentLength(buffer));
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = makeBuffer(sizeof(isl->saveData), &buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = encodeIndexSaveData(buffer, &isl->saveData);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = writeToBufferedWriter(writer, getBufferContents(buffer),
|
|
Packit Service |
310c69 |
contentLength(buffer));
|
|
Packit Service |
310c69 |
freeBuffer(&buffer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (isl->indexStateBuffer != NULL) {
|
|
Packit Service |
310c69 |
result = writeToBufferedWriter(writer,
|
|
Packit Service |
310c69 |
getBufferContents(isl->indexStateBuffer),
|
|
Packit Service |
310c69 |
contentLength(isl->indexStateBuffer));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return flushBufferedWriter(writer);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
static int writeIndexSaveLayout(IndexLayout *layout, IndexSaveLayout *isl)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
unsigned int numRegions;
|
|
Packit Service |
310c69 |
RegionTable *table;
|
|
Packit Service |
310c69 |
int result = makeIndexSaveRegionTable(isl, &numRegions, &table);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
BufferedWriter *writer = NULL;
|
|
Packit Service |
310c69 |
result = openLayoutWriter(layout, &isl->header, &writer);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = writeIndexSaveHeader(isl, table, numRegions, writer);
|
|
Packit Service |
310c69 |
FREE(table);
|
|
Packit Service |
310c69 |
freeBufferedWriter(writer);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
isl->written = true;
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int commitIndexSave(IndexLayout *layout, unsigned int saveSlot)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = ASSERT((saveSlot < layout->super.maxSaves),
|
|
Packit Service |
310c69 |
"save slot out of range");
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl = &layout->index.saves[saveSlot];
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (bufferUsed(isl->indexStateBuffer) == 0) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_UNEXPECTED_RESULT,
|
|
Packit Service |
310c69 |
"%s: no index state data saved", __func__);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return writeIndexSaveLayout(layout, isl);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
static void mutilateIndexSaveInfo(IndexSaveLayout *isl)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
memset(&isl->saveData, 0, sizeof(isl->saveData));
|
|
Packit Service |
310c69 |
isl->read = isl->written = 0;
|
|
Packit Service |
310c69 |
isl->saveType = NO_SAVE;
|
|
Packit Service |
310c69 |
isl->numZones = 0;
|
|
Packit Service |
310c69 |
freeBuffer(&isl->indexStateBuffer);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int cancelIndexSave(IndexLayout *layout, unsigned int saveSlot)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = ASSERT((saveSlot < layout->super.maxSaves),
|
|
Packit Service |
310c69 |
"save slot out of range");
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
mutilateIndexSaveInfo(&layout->index.saves[saveSlot]);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int discardIndexSaves(IndexLayout *layout, bool all)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = UDS_SUCCESS;
|
|
Packit Service |
310c69 |
SubIndexLayout *sil = &layout->index;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (all) {
|
|
Packit Service |
310c69 |
unsigned int i;
|
|
Packit Service |
310c69 |
for (i = 0; i < layout->super.maxSaves; ++i) {
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl = &sil->saves[i];
|
|
Packit Service |
310c69 |
result = firstError(result, invalidateOldSave(layout, isl));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
} else {
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl;
|
|
Packit Service |
310c69 |
result = selectLatestIndexSaveLayout(sil, layout->super.maxSaves, &isl;;
|
|
Packit Service |
310c69 |
if (result == UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
result = invalidateOldSave(layout, isl);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
static int createIndexLayout(IndexLayout *layout,
|
|
Packit Service |
310c69 |
uint64_t size,
|
|
Packit Service |
310c69 |
const UdsConfiguration config)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (config == NULL) {
|
|
Packit Service |
310c69 |
return UDS_CONF_PTR_REQUIRED;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
SaveLayoutSizes sizes;
|
|
Packit Service |
310c69 |
int result = computeSizes(&sizes, config, UDS_BLOCK_SIZE, 0);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (size < sizes.totalBlocks * sizes.blockSize) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_INSUFFICIENT_INDEX_SPACE,
|
|
Packit Service |
310c69 |
"layout requires at least %" PRIu64
|
|
Packit Service |
310c69 |
" bytes",
|
|
Packit Service |
310c69 |
sizes.totalBlocks * sizes.blockSize);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = initSingleFileLayout(layout, layout->offset, size, &sizes);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = saveSingleFileConfiguration(layout);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
Buffer *getIndexStateBuffer(IndexLayout *layout, unsigned int slot)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return layout->index.saves[slot].indexStateBuffer;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
static int findLayoutRegion(IndexLayout *layout,
|
|
Packit Service |
310c69 |
unsigned int slot,
|
|
Packit Service |
310c69 |
const char *operation,
|
|
Packit Service |
310c69 |
RegionKind kind,
|
|
Packit Service |
310c69 |
unsigned int zone,
|
|
Packit Service |
310c69 |
LayoutRegion **lrPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = ASSERT((slot < layout->super.maxSaves), "%s not started",
|
|
Packit Service |
310c69 |
operation);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
IndexSaveLayout *isl = &layout->index.saves[slot];
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
LayoutRegion *lr = NULL;
|
|
Packit Service |
310c69 |
switch (kind) {
|
|
Packit Service |
310c69 |
case RL_KIND_INDEX_PAGE_MAP:
|
|
Packit Service |
310c69 |
lr = &isl->indexPageMap;
|
|
Packit Service |
310c69 |
break;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
case RL_KIND_OPEN_CHAPTER:
|
|
Packit Service |
310c69 |
if (isl->openChapter == NULL) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_UNEXPECTED_RESULT,
|
|
Packit Service |
310c69 |
"%s: %s has no open chapter",
|
|
Packit Service |
310c69 |
__func__, operation);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
lr = isl->openChapter;
|
|
Packit Service |
310c69 |
break;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
case RL_KIND_MASTER_INDEX:
|
|
Packit Service |
310c69 |
if (isl->masterIndexZones == NULL || zone >= isl->numZones) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_UNEXPECTED_RESULT,
|
|
Packit Service |
310c69 |
"%s: %s has no master index zone %u",
|
|
Packit Service |
310c69 |
__func__, operation, zone);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
lr = &isl->masterIndexZones[zone];
|
|
Packit Service |
310c69 |
break;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
default:
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_INVALID_ARGUMENT,
|
|
Packit Service |
310c69 |
"%s: unexpected kind %u",
|
|
Packit Service |
310c69 |
__func__, kind);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*lrPtr = lr;
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int openIndexBufferedReader(IndexLayout *layout,
|
|
Packit Service |
310c69 |
unsigned int slot,
|
|
Packit Service |
310c69 |
RegionKind kind,
|
|
Packit Service |
310c69 |
unsigned int zone,
|
|
Packit Service |
310c69 |
BufferedReader **readerPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
LayoutRegion *lr = NULL;
|
|
Packit Service |
310c69 |
int result = findLayoutRegion(layout, slot, "load", kind, zone, &lr);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return openLayoutReader(layout, lr, readerPtr);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int openIndexBufferedWriter(IndexLayout *layout,
|
|
Packit Service |
310c69 |
unsigned int slot,
|
|
Packit Service |
310c69 |
RegionKind kind,
|
|
Packit Service |
310c69 |
unsigned int zone,
|
|
Packit Service |
310c69 |
BufferedWriter **writerPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
LayoutRegion *lr = NULL;
|
|
Packit Service |
310c69 |
int result = findLayoutRegion(layout, slot, "save", kind, zone, &lr);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return openLayoutWriter(layout, lr, writerPtr);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int makeIndexLayoutFromFactory(IOFactory *factory,
|
|
Packit Service |
310c69 |
off_t offset,
|
|
Packit Service |
310c69 |
uint64_t namedSize,
|
|
Packit Service |
310c69 |
bool newLayout,
|
|
Packit Service |
310c69 |
const UdsConfiguration config,
|
|
Packit Service |
310c69 |
IndexLayout **layoutPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
// Get the device size and round it down to a multiple of UDS_BLOCK_SIZE.
|
|
Packit Service |
310c69 |
size_t size = getWritableSize(factory) & -UDS_BLOCK_SIZE;
|
|
Packit Service |
310c69 |
if (namedSize > size) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_INSUFFICIENT_INDEX_SPACE,
|
|
Packit Service |
310c69 |
"index storage (%zu) is smaller than the"
|
|
Packit Service |
310c69 |
" requested size %llu",
|
|
Packit Service |
310c69 |
size, namedSize);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if ((namedSize > 0) && (namedSize < size)) {
|
|
Packit Service |
310c69 |
size = namedSize;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// Get the index size according the the config
|
|
Packit Service |
310c69 |
uint64_t configSize;
|
|
Packit Service |
310c69 |
int result = udsComputeIndexSize(config, 0, &configSize);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (size < configSize) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_INSUFFICIENT_INDEX_SPACE,
|
|
Packit Service |
310c69 |
"index storage (%zu) is smaller than the"
|
|
Packit Service |
310c69 |
" required size %llu",
|
|
Packit Service |
310c69 |
size, configSize);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
size = configSize;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
IndexLayout *layout = NULL;
|
|
Packit Service |
310c69 |
result = ALLOCATE(1, IndexLayout, __func__, &layout);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
layout->refCount = 1;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
getIOFactory(factory);
|
|
Packit Service |
310c69 |
layout->factory = factory;
|
|
Packit Service |
310c69 |
layout->offset = offset;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (newLayout) {
|
|
Packit Service |
310c69 |
// Populate the layout from the UDSConfiguration
|
|
Packit Service |
310c69 |
result = createIndexLayout(layout, size, config);
|
|
Packit Service |
310c69 |
} else {
|
|
Packit Service |
310c69 |
// Populate the layout from the saved index.
|
|
Packit Service |
310c69 |
result = loadIndexLayout(layout);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
putIndexLayout(&layout);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
*layoutPtr = layout;
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|