/* * 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/vdoPageCache.h#7 $ */ #ifndef VDO_PAGE_CACHE_H #define VDO_PAGE_CACHE_H #include "adminState.h" #include "atomic.h" #include "completion.h" #include "types.h" #include "waitQueue.h" /** * Structure describing page meta data (defined internally). **/ typedef struct pageInfo PageInfo; /** * Structure describing entire page cache. * (Unfortunately the name "PageCache" is already taken by Albireo.) **/ typedef struct vdoPageCache VDOPageCache; /** * Generation counter for page references. **/ typedef uint32_t VDOPageGeneration; /** * Page-state count statistics sub-structure. **/ typedef struct { /* free pages */ Atomic64 freePages; /* clean (resident) pages */ Atomic64 cleanPages; /* dirty pages per era */ Atomic64 dirtyPages; /* pages incoming */ Atomic64 incomingPages; /* pages outgoing */ Atomic64 outgoingPages; /* pages in failed state */ Atomic64 failedPages; } AtomicPageStateCounts; /** * Statistics and debugging fields for the page cache. */ typedef struct { /* counts of how many pages are in each state */ AtomicPageStateCounts counts; /* how many times free page not available */ Atomic64 cachePressure; /* number of getVDOPageAsync() for read */ Atomic64 readCount; /* number or getVDOPageAsync() for write */ Atomic64 writeCount; /* number of times pages failed to read */ Atomic64 failedReads; /* number of times pages failed to write */ Atomic64 failedWrites; /* number of gets that are reclaimed */ Atomic64 reclaimed; /* number of gets for outgoing pages */ Atomic64 readOutgoing; /* number of gets that were already there */ Atomic64 foundInCache; /* number of gets requiring discard */ Atomic64 discardRequired; /* number of gets enqueued for their page */ Atomic64 waitForPage; /* number of gets that have to fetch */ Atomic64 fetchRequired; /* number of page fetches */ Atomic64 pagesLoaded; /* number of page saves */ Atomic64 pagesSaved; /* number of flushes initiated */ Atomic64 flushCount; } AtomicPageCacheStatistics; /** * Signature for a function to call when a page is read into the cache. * *
If specified, this function is called when a page is fetched from disk. * * @param rawPage The raw memory of the freshly-fetched page * @param pbn The absolute physical block number of the page * @param zone The block map zone to which the cache belongs * @param pageContext A pointer to client-specific data for the new page * * @return VDO_SUCCESS on success or VDO_BAD_PAGE if the page is incorrectly * formatted **/ typedef int VDOPageReadFunction(void *rawPage, PhysicalBlockNumber pbn, BlockMapZone *zone, void *pageContext); /** * Signature for a function to call when a page is written from the cache. * *
If specified, this function is called when a page is written to disk.
*
* @param rawPage The raw memory of the freshly-written page
* @param zone The block map zone to which the cache belongs
* @param pageContext A pointer to client-specific data for the new page
*
* @return whether the page needs to be rewritten
**/
typedef bool VDOPageWriteFunction(void *rawPage,
BlockMapZone *zone,
void *pageContext);
/**
* Construct a PageCache.
*
* @param [in] layer The physical layer to read and write
* @param [in] pageCount The number of cache pages to hold
* @param [in] readHook The function to be called when a page is read
* into the cache
* @param [in] writeHook The function to be called after a page is
* written from the cache
* @param [in] pageContextSize The size of the per-page context that will be
* passed to the read and write hooks
* @param [in] maximumAge The number of journal blocks before a dirtied
* page is considered old and must be written
* out
* @param [in] zone The block map zone which owns this cache
* @param [out] cachePtr A pointer to hold the cache
*
* @return a success or error code
**/
int makeVDOPageCache(PhysicalLayer *layer,
PageCount pageCount,
VDOPageReadFunction *readHook,
VDOPageWriteFunction *writeHook,
size_t pageContextSize,
BlockCount maximumAge,
BlockMapZone *zone,
VDOPageCache **cachePtr)
__attribute__((warn_unused_result));
/**
* Free the page cache structure and null out the reference to it.
*
* @param cachePtr a pointer to the cache to free
**/
void freeVDOPageCache(VDOPageCache **cachePtr);
/**
* Set the initial dirty period for a page cache.
*
* @param cache The cache
* @param period The initial dirty period to set
**/
void setVDOPageCacheInitialPeriod(VDOPageCache *cache, SequenceNumber period);
/**
* Switch the page cache into or out of read-only rebuild mode.
*
* @param cache The cache
* @param rebuilding true
if the cache should be put into
* read-only rebuild mode, false
otherwise
**/
void setVDOPageCacheRebuildMode(VDOPageCache *cache, bool rebuilding);
/**
* Check whether a page cache is active (i.e. has any active lookups,
* outstanding I/O, or pending I/O).
*
* @param cache The cache to check
*
* @return true
if the cache is active
**/
bool isPageCacheActive(VDOPageCache *cache)
__attribute__((warn_unused_result));
/**
* Advance the dirty period for a page cache.
*
* @param cache The cache to advance
* @param period The new dirty period
**/
void advanceVDOPageCachePeriod(VDOPageCache *cache, SequenceNumber period);
/**
* Write one or more batches of dirty pages.
*
* All writable pages in the ancient era and some number in the old era
* are scheduled for writing.
*
* @param cache the VDO page cache
* @param batches how many batches to write now
* @param total how many batches (including those being written now) remain
* in this era
**/
void writeVDOPageCachePages(VDOPageCache *cache,
size_t batches,
size_t total);
/**
* Rotate the dirty page eras.
*
* Move all pages in the old era to the ancient era and then move
* the current era bin into the old era.
*
* @param cache the VDO page cache
**/
void rotateVDOPageCacheEras(VDOPageCache *cache);
// ASYNC
/**
* A completion awaiting a specific page. Also a live reference into the
* page once completed, until freed.
**/
typedef struct {
/** The generic completion */
VDOCompletion completion;
/** The cache involved */
VDOPageCache *cache;
/** The waiter for the pending list */
Waiter waiter;
/** The absolute physical block number of the page on disk */
PhysicalBlockNumber pbn;
/** Whether the page may be modified */
bool writable;
/** Whether the page is available */
bool ready;
/** The info structure for the page, only valid when ready */
PageInfo *info;
} VDOPageCompletion;
/**
* Initialize a VDO Page Completion, requesting a particular page from the
* cache.
*
* @param pageCompletion The VDOPageCompletion to initialize
* @param cache The VDO page cache
* @param pbn The absolute physical block of the desired page
* @param writable Whether the page can be modified
* @param parent The parent object
* @param callback The completion callback
* @param errorHandler The handler for page errors
*
* @note Once a completion has occurred for the getVDOPageAsync operation,
* the underlying page shall be busy (stuck in memory) until the
* VDOCompletion returned by this operation has been released.
**/
void initVDOPageCompletion(VDOPageCompletion *pageCompletion,
VDOPageCache *cache,
PhysicalBlockNumber pbn,
bool writable,
void *parent,
VDOAction *callback,
VDOAction *errorHandler);
/**
* Release a VDO Page Completion.
*
* The page referenced by this completion (if any) will no longer be
* held busy by this completion. If a page becomes discardable and
* there are completions awaiting free pages then a new round of
* page discarding is started.
*
* @param completion The completion to release
**/
void releaseVDOPageCompletion(VDOCompletion *completion);
/**
* Asynchronous operation to get a VDO page.
*
* May cause another page to be discarded (potentially writing a dirty page)
* and the one nominated by the completion to be loaded from disk.
*
* When the page becomes available the callback registered in the completion
* provided is triggered. Once triggered the page is marked busy until
* the completion is destroyed.
*
* @param completion the completion initialized my initVDOPageCompletion().
**/
void getVDOPageAsync(VDOCompletion *completion);
/**
* Mark a VDO page referenced by a completed VDOPageCompletion as dirty.
*
* @param completion a VDO Page Completion whose callback has been called
* @param oldDirtyPeriod the period in which the page was already dirty (0 if
* it wasn't)
* @param newDirtyPeriod the period in which the page is now dirty
**/
void markCompletedVDOPageDirty(VDOCompletion *completion,
SequenceNumber oldDirtyPeriod,
SequenceNumber newDirtyPeriod);
/**
* Request that a VDO page be written out as soon as it is not busy.
*
* @param completion the VDOPageCompletion containing the page
**/
void requestVDOPageWrite(VDOCompletion *completion);
/**
* Access the raw memory for a read-only page of a completed VDOPageCompletion.
*
* @param completion a vdo page completion whose callback has been called
*
* @return a pointer to the raw memory at the beginning of the page, or
* NULL if the page is not available.
**/
const void *dereferenceReadableVDOPage(VDOCompletion *completion);
/**
* Access the raw memory for a writable page of a completed VDOPageCompletion.
*
* @param completion a vdo page completion whose callback has been called
*
* @return a pointer to the raw memory at the beginning of the page, or
* NULL if the page is not available, or if the page is read-only
**/
void *dereferenceWritableVDOPage(VDOCompletion *completion);
/**
* Get the per-page client context for the page in a page completion whose
* callback has been invoked. Should only be called after dereferencing the
* page completion to validate the page.
*
* @param completion a vdo page completion whose callback has been invoked
*
* @return a pointer to the per-page client context, or NULL if
* the page is not available
**/
void *getVDOPageCompletionContext(VDOCompletion *completion);
/**
* Drain I/O for a page cache.
*
* @param cache The cache to drain
**/
void drainVDOPageCache(VDOPageCache *cache);
/**
* Invalidate all entries in the VDO page cache. There must not be any
* dirty pages in the cache.
*
* @param cache the cache to invalidate
*
* @return a success or error code
**/
int invalidateVDOPageCache(VDOPageCache *cache)
__attribute__((warn_unused_result));
// STATISTICS & TESTING
/**
* Get current cache statistics.
*
* @param cache the page cache
*
* @return the statistics
**/
AtomicPageCacheStatistics *getVDOPageCacheStatistics(VDOPageCache *cache)
__attribute__((warn_unused_result));
#endif // VDO_PAGE_CACHE_H