/*
* Copyright (c) 2020 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/blockMapInternals.h#12 $
*/
#ifndef BLOCK_MAP_INTERNALS_H
#define BLOCK_MAP_INTERNALS_H
#include "adminState.h"
#include "blockMapEntry.h"
#include "blockMapTree.h"
#include "completion.h"
#include "dirtyLists.h"
#include "header.h"
#include "intMap.h"
#include "ringNode.h"
#include "types.h"
#include "vdoPageCache.h"
#include "vioPool.h"
/**
* The per-zone fields used by the block map tree.
**/
struct blockMapTreeZone {
/** The BlockMapZone which owns this tree zone */
BlockMapZone *mapZone;
/** The lists of dirty tree pages */
DirtyLists *dirtyLists;
/** The number of tree lookups in progress */
VIOCount activeLookups;
/** The map of pages currently being loaded */
IntMap *loadingPages;
/** The pool of VIOs for tree I/O */
VIOPool *vioPool;
/** The tree page which has issued or will be issuing a flush */
TreePage *flusher;
/** The queue of pages waiting for a flush so they can be written out */
WaitQueue flushWaiters;
/** The generation after the most recent flush */
uint8_t generation;
/** The oldest active generation */
uint8_t oldestGeneration;
/** The counts of dirty pages in each generation */
uint32_t dirtyPageCounts[256];
};
/**
* The per-zone fields of the block map.
**/
struct blockMapZone {
/** The number of the zone this is */
ZoneCount zoneNumber;
/** The ID of this zone's logical thread */
ThreadID threadID;
/** The BlockMap which owns this BlockMapZone */
BlockMap *blockMap;
/** The ReadOnlyNotifier of the VDO */
ReadOnlyNotifier *readOnlyNotifier;
/** The page cache for this zone */
VDOPageCache *pageCache;
/** The per-zone portion of the tree for this zone */
BlockMapTreeZone treeZone;
/** The administrative state of the zone */
AdminState state;
};
struct blockMap {
/** The manager for block map actions */
ActionManager *actionManager;
/** The count of pages in the linear part of the block map */
BlockCount flatPageCount;
/** The absolute PBN of the first root of the tree part of the block map */
PhysicalBlockNumber rootOrigin;
/** The count of root pages of the tree part of the block map */
BlockCount rootCount;
/** The era point we are currently distributing to the zones */
SequenceNumber currentEraPoint;
/** The next era point, not yet distributed to any zone */
SequenceNumber pendingEraPoint;
/** The number of entries in block map */
BlockCount entryCount;
/** The VDO's nonce, for the pages */
Nonce nonce;
/** The recovery journal for this map */
RecoveryJournal *journal;
/** The trees for finding block map pages */
Forest *forest;
/** The expanded trees awaiting growth */
Forest *nextForest;
/** The number of entries after growth */
BlockCount nextEntryCount;
/** The number of logical zones */
ZoneCount zoneCount;
/** The per zone block map structure */
BlockMapZone zones[];
};
/**
* Compute the number of pages required for a block map with the specified
* parameters.
*
* @param entries The number of block map entries
*
* @return The number of pages required
**/
PageCount computeBlockMapPageCount(BlockCount entries);
/**
* Compute the number of the block map page on which the entry for a given
* logical block resides.
*
* @param lbn The logical block number whose page is desired
*
* @return The number of the block map page containing the entry for
* the given logical block number
**/
__attribute__((warn_unused_result))
static inline PageNumber computePageNumber(LogicalBlockNumber lbn)
{
return (lbn / BLOCK_MAP_ENTRIES_PER_PAGE);
}
/**
* Find the block map page slot in which the entry for a given logical
* block resides.
*
* @param lbn The logical block number whose slot
*
* @return The slot containing the entry for the given logical block number
**/
__attribute__((warn_unused_result))
static inline SlotNumber computeSlot(LogicalBlockNumber lbn)
{
return (lbn % BLOCK_MAP_ENTRIES_PER_PAGE);
}
/**
* Check whether a zone of the block map has drained, and if so, send a
* notification thereof.
*
* @param zone The zone to check
**/
void checkForDrainComplete(BlockMapZone *zone);
#endif // BLOCK_MAP_INTERNALS_H