|
Packit Service |
75d76b |
/*
|
|
Packit Service |
75d76b |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
75d76b |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
75d76b |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
75d76b |
* of the License, or (at your option) any later version.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
75d76b |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
75d76b |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
75d76b |
* GNU General Public License for more details.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
75d76b |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
75d76b |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
75d76b |
* 02110-1301, USA.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/recoveryJournalBlock.h#8 $
|
|
Packit Service |
75d76b |
*/
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#ifndef RECOVERY_JOURNAL_BLOCK_H
|
|
Packit Service |
75d76b |
#define RECOVERY_JOURNAL_BLOCK_H
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#include "permassert.h"
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#include "packedRecoveryJournalBlock.h"
|
|
Packit Service |
75d76b |
#include "recoveryJournalInternals.h"
|
|
Packit Service |
75d76b |
#include "ringNode.h"
|
|
Packit Service |
75d76b |
#include "types.h"
|
|
Packit Service |
75d76b |
#include "waitQueue.h"
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
struct recoveryJournalBlock {
|
|
Packit Service |
75d76b |
/** The doubly linked pointers for the free or active lists */
|
|
Packit Service |
75d76b |
RingNode ringNode;
|
|
Packit Service |
75d76b |
/** The waiter for the pending full block list */
|
|
Packit Service |
75d76b |
Waiter writeWaiter;
|
|
Packit Service |
75d76b |
/** The journal to which this block belongs */
|
|
Packit Service |
75d76b |
RecoveryJournal *journal;
|
|
Packit Service |
75d76b |
/** A pointer to a block-sized buffer holding the packed block data */
|
|
Packit Service |
75d76b |
char *block;
|
|
Packit Service |
75d76b |
/** A pointer to the current sector in the packed block buffer */
|
|
Packit Service |
75d76b |
PackedJournalSector *sector;
|
|
Packit Service |
75d76b |
/** The VIO for writing this block */
|
|
Packit Service |
75d76b |
VIO *vio;
|
|
Packit Service |
75d76b |
/** The sequence number for this block */
|
|
Packit Service |
75d76b |
SequenceNumber sequenceNumber;
|
|
Packit Service |
75d76b |
/** The location of this block in the on-disk journal */
|
|
Packit Service |
75d76b |
PhysicalBlockNumber blockNumber;
|
|
Packit Service |
75d76b |
/** Whether this block is being committed */
|
|
Packit Service |
75d76b |
bool committing;
|
|
Packit Service |
75d76b |
/** Whether this block has an uncommitted increment for a partial write */
|
|
Packit Service |
75d76b |
bool hasPartialWriteEntry;
|
|
Packit Service |
75d76b |
/** Whether this block has an uncommitted increment for a write with FUA */
|
|
Packit Service |
75d76b |
bool hasFUAEntry;
|
|
Packit Service |
75d76b |
/** The total number of entries in this block */
|
|
Packit Service |
75d76b |
JournalEntryCount entryCount;
|
|
Packit Service |
75d76b |
/** The total number of uncommitted entries (queued or committing) */
|
|
Packit Service |
75d76b |
JournalEntryCount uncommittedEntryCount;
|
|
Packit Service |
75d76b |
/** The number of new entries in the current commit */
|
|
Packit Service |
75d76b |
JournalEntryCount entriesInCommit;
|
|
Packit Service |
75d76b |
/** The queue of VIOs which will make entries for the next commit */
|
|
Packit Service |
75d76b |
WaitQueue entryWaiters;
|
|
Packit Service |
75d76b |
/** The queue of VIOs waiting for the current commit */
|
|
Packit Service |
75d76b |
WaitQueue commitWaiters;
|
|
Packit Service |
75d76b |
};
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Return the block associated with a ring node.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param node The ring node to recast as a block
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @return The block
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
static inline RecoveryJournalBlock *blockFromRingNode(RingNode *node)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
STATIC_ASSERT(offsetof(RecoveryJournalBlock, ringNode) == 0);
|
|
Packit Service |
75d76b |
return (RecoveryJournalBlock *) node;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Return the block associated with a waiter
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param waiter The waiter to recast as a block
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @return The block
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
static inline RecoveryJournalBlock *blockFromWaiter(Waiter *waiter)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
return (RecoveryJournalBlock *)
|
|
Packit Service |
75d76b |
((uintptr_t) waiter - offsetof(RecoveryJournalBlock, writeWaiter));
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Check whether a recovery block is dirty, indicating it has any uncommitted
|
|
Packit Service |
75d76b |
* entries, which includes both entries not written and entries written but
|
|
Packit Service |
75d76b |
* not yet acknowledged.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param block The block to check
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @return true if the block has any uncommitted entries
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
__attribute__((warn_unused_result))
|
|
Packit Service |
75d76b |
static inline bool isRecoveryBlockDirty(const RecoveryJournalBlock *block)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
return (block->uncommittedEntryCount > 0);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Check whether a journal block is empty.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param block The block to check
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @return true if the block has no entries
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
__attribute__((warn_unused_result))
|
|
Packit Service |
75d76b |
static inline bool isRecoveryBlockEmpty(const RecoveryJournalBlock *block)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
return (block->entryCount == 0);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Check whether a journal block is full.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param block The block to check
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @return true if the the block is full
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
__attribute__((warn_unused_result))
|
|
Packit Service |
75d76b |
static inline bool isRecoveryBlockFull(const RecoveryJournalBlock *block)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
return ((block == NULL)
|
|
Packit Service |
75d76b |
|| (block->journal->entriesPerBlock == block->entryCount));
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Construct a journal block.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param [in] layer The layer from which to construct VIOs
|
|
Packit Service |
75d76b |
* @param [in] journal The journal to which the block will belong
|
|
Packit Service |
75d76b |
* @param [out] blockPtr A pointer to receive the new block
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @return VDO_SUCCESS or an error
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
int makeRecoveryBlock(PhysicalLayer *layer,
|
|
Packit Service |
75d76b |
RecoveryJournal *journal,
|
|
Packit Service |
75d76b |
RecoveryJournalBlock **blockPtr)
|
|
Packit Service |
75d76b |
__attribute__((warn_unused_result));
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Free a tail block and null out the reference to it.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param blockPtr The reference to the tail block to free
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
void freeRecoveryBlock(RecoveryJournalBlock **blockPtr);
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Initialize the next active recovery journal block.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param block The journal block to initialize
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
void initializeRecoveryBlock(RecoveryJournalBlock *block);
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Enqueue a DataVIO to asynchronously encode and commit its next recovery
|
|
Packit Service |
75d76b |
* journal entry in this block. The DataVIO will not be continued until the
|
|
Packit Service |
75d76b |
* entry is committed to the on-disk journal. The caller is responsible for
|
|
Packit Service |
75d76b |
* ensuring the block is not already full.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param block The journal block in which to make an entry
|
|
Packit Service |
75d76b |
* @param dataVIO The DataVIO to enqueue
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @return VDO_SUCCESS or an error code if the DataVIO could not be enqueued
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
int enqueueRecoveryBlockEntry(RecoveryJournalBlock *block, DataVIO *dataVIO)
|
|
Packit Service |
75d76b |
__attribute__((warn_unused_result));
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Attempt to commit a block. If the block is not the oldest block with
|
|
Packit Service |
75d76b |
* uncommitted entries or if it is already being committed, nothing will be
|
|
Packit Service |
75d76b |
* done.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param block The block to write
|
|
Packit Service |
75d76b |
* @param callback The function to call when the write completes
|
|
Packit Service |
75d76b |
* @param errorHandler The handler for flush or write errors
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @return VDO_SUCCESS, or an error if the write could not be launched
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
int commitRecoveryBlock(RecoveryJournalBlock *block,
|
|
Packit Service |
75d76b |
VDOAction *callback,
|
|
Packit Service |
75d76b |
VDOAction *errorHandler)
|
|
Packit Service |
75d76b |
__attribute__((warn_unused_result));
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Dump the contents of the recovery block to the log.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param block The block to dump
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
void dumpRecoveryBlock(const RecoveryJournalBlock *block);
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**
|
|
Packit Service |
75d76b |
* Check whether a journal block can be committed.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @param block The journal block in question
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* @return true if the block can be committed now
|
|
Packit Service |
75d76b |
**/
|
|
Packit Service |
75d76b |
bool canCommitRecoveryBlock(RecoveryJournalBlock *block)
|
|
Packit Service |
75d76b |
__attribute__((warn_unused_result));
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#endif // RECOVERY_JOURNAL_BLOCK_H
|